diff options
author | 2017-09-28 10:03:40 -0700 | |
---|---|---|
committer | 2017-09-28 10:14:55 -0700 | |
commit | bd886d918ef2adbabd16c61fdd2e47984e21dfd7 (patch) | |
tree | d41683dffa58fd698df450d148fab3cc2521b0c5 /django/engagementmanager | |
parent | 474554adad912f3edb7ddc3ad14406abb369fb3c (diff) |
initial seed code commit VVP-5
Change-Id: I6560c87ef48a6d0d1fe8197c7c6439c7e6ad653f
Signed-off-by: Paul McGoldrick <paul.mcgoldrick@att.com>
Diffstat (limited to 'django/engagementmanager')
197 files changed, 26226 insertions, 0 deletions
diff --git a/django/engagementmanager/__init__.py b/django/engagementmanager/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/admin.py b/django/engagementmanager/admin.py new file mode 100755 index 0000000..38a63f8 --- /dev/null +++ b/django/engagementmanager/admin.py @@ -0,0 +1,380 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.contrib import admin + +from engagementmanager import models + + +@admin.register(models.Activity) +class ActivityModelAdmin(admin.ModelAdmin): + + list_display = ["engagement_manual_id", "vf_name", "description", + "activity_type", "activity_owner", "create_time", "is_notification"] + list_filter = ["activity_type", "is_notification"] + + def engagement_manual_id(self, obj): + if obj.engagement: + return obj.engagement.engagement_manual_id + else: + return "" + + def vf_name(self, obj): + if obj.engagement: + return models.VF.objects.get(engagement=obj.engagement).name + else: + return "" + + def get_readonly_fields(self, request, obj=None): + if obj: # editing an existing object + return self.readonly_fields + ('create_time',) + return self.readonly_fields + + +@admin.register(models.Checklist) +class ChecklistModelAdmin(admin.ModelAdmin): + + list_display = ["name", "state", "engagement_manual_id", "vf_name", "validation_cycle", + "weight", "template", "owner", "creator", "associated_files", "create_time", "update_time"] + list_filter = ["template", "state"] + search_fields = ["name", "associated_files"] + + def engagement_manual_id(self, obj): + return obj.engagement.engagement_manual_id + + def vf_name(self, obj): + return models.VF.objects.get(engagement=obj.engagement).name + + +@admin.register(models.ChecklistAuditLog) +class ChecklistAuditLogModelAdmin(admin.ModelAdmin): + + list_display = ["description", "creator", "checklist", "create_time", "update_time"] + list_filter = ["category"] + search_fields = ["description"] + + +@admin.register(models.ChecklistDecision) +class ChecklistDecisionModelAdmin(admin.ModelAdmin): + + list_display = ["checklist", "lineitem", "review_value", "peer_review_value", "create_time", "update_time"] + list_filter = ["template"] + search_fields = ["name"] + + +@admin.register(models.ChecklistLineItem) +class ChecklistLineItemModelAdmin(admin.ModelAdmin): + + list_display = ["name", "weight", "template", "section", "create_time", "update_time"] + list_filter = ["template", "section"] + search_fields = ["name"] + + +@admin.register(models.ChecklistSection) +class ChecklistSectionModelAdmin(admin.ModelAdmin): + + list_display = ["name", "weight", "template", "parent_section", "create_time", "update_time"] + list_filter = ["template"] + + +@admin.register(models.ChecklistTemplate) +class ChecklistTemplateModelAdmin(admin.ModelAdmin): + + list_display = ["name", "category", "version", "create_time", "update_time"] + list_filter = ["category", "version"] + search_fields = ["name"] + search_fields = ["name"] + + +@admin.register(models.DeploymentTarget) +class DeploymentTargetModelAdmin(admin.ModelAdmin): + + list_display = ["name", "version"] + list_filter = ["version"] + + +@admin.register(models.DeploymentTargetSite) +class DeploymentTargetSiteModelAdmin(admin.ModelAdmin): + + list_display = ["name"] + + +@admin.register(models.Engagement) +class EngagementModelAdmin(admin.ModelAdmin): + + list_display = ["engagement_manual_id", "vf_name", "deployment_target_name", "ecomp_release", "progress", "target_completion_date", + "target_lab_entry_date", "engagement_stage", "create_time"] + list_editable = ["progress", "target_completion_date", "engagement_stage"] + list_filter = ["engagement_stage"] + search_fields = ["engagement_stage", "engagement_manual_id"] + + def vf_name(self, obj): + return models.VF.objects.get(engagement=obj).name + + def target_lab_entry_date(self, obj): + return models.VF.objects.get(engagement=obj).target_lab_entry_date + + def ecomp_release(self, obj): + return models.VF.objects.get(engagement=obj).ecomp_release + + def deployment_target_name(self, obj): + e = models.VF.objects.get(engagement=obj) + return e.deployment_target.name + " " + e.deployment_target.version + + def get_readonly_fields(self, request, obj=None): + if obj: # editing an existing object + return self.readonly_fields + ('create_time',) + return self.readonly_fields + + +@admin.register(models.EngagementStatus) +class EngagementStatusModelAdmin(admin.ModelAdmin): + + list_display = ["engagement_manual_id", "vf_name", "description", "creator_full_name", "create_time", "update_time"] + list_filter = ["creator"] + search_fields = ["description"] + + def engagement_manual_id(self, obj): + return obj.engagement.engagement_manual_id + + def vf_name(self, obj): + return models.VF.objects.get(engagement=obj.engagement).name + + def creator_full_name(self, obj): + return obj.creator.full_name + + +@admin.register(models.ECOMPRelease) +class ECOMPReleaseModelAdmin(admin.ModelAdmin): + + list_display = ["name"] + search_fields = ["name"] + + +@admin.register(models.IceUserProfile) +class IceUserProfileModelAdmin(admin.ModelAdmin): + + list_display = ["full_name", "email", "phone_number", "company_name", "role_name", "is_service_provider_contact", "has_ssh_key", + "create_time", "role"] + list_editable = ["phone_number", "is_service_provider_contact", "role"] + list_filter = ["is_service_provider_contact", "role", "company"] + search_fields = ["full_name", "email", "phone_number"] + + def company_name(self, obj): + return obj.company.name + + def role_name(self, obj): + return obj.role.name + + def has_ssh_key(self, obj): + if obj.ssh_public_key: + return True + else: + return False + + def get_readonly_fields(self, request, obj=None): + if obj: # editing an existing object + return self.readonly_fields + ('create_time',) + return self.readonly_fields + + +@admin.register(models.Invitation) +class InvitationModelAdmin(admin.ModelAdmin): + + list_display = ["email", "engagement_manual_id", "vf_name", + "invited_by_user", "accepted", "create_time", "invitation_token"] + list_filter = ["accepted"] + search_fields = ["email", "invitation_token"] + + def invited_by_user(self, obj): + return models.IceUserProfile.objects.get(uuid=obj.invited_by_user_uuid).full_name + + def engagement_manual_id(self, obj): + return models.Engagement.objects.get(uuid=obj.engagement_uuid).engagement_manual_id + + def vf_name(self, obj): + e = models.Engagement.objects.get(uuid=obj.engagement_uuid) + return models.VF.objects.get(engagement=e).name + + +@admin.register(models.NextStep) +class NextStepModelAdmin(admin.ModelAdmin): + + list_display = ["engagement_manual_id", "vf_name", "description", "files", "due_date", "last_updater_full_name", "last_update_time", + "last_update_type", "creator_full_name", "create_time", "state", "next_step_type", "owner_full_name"] + list_filter = ["next_step_type", "state"] + search_fields = ["description", "files"] + + def engagement_manual_id(self, obj): + e = obj.engagement + if e: + return e.engagement_manual_id + else: + return "" + + def vf_name(self, obj): + e = obj.engagement + if e: + return models.VF.objects.get(engagement=e).name + else: + return "" + + def creator_full_name(self, obj): + c = obj.creator + if c: + return c.full_name + else: + return "" + + def last_updater_full_name(self, obj): + lu = obj.last_updater + if lu: + return lu.full_name + else: + return "" + + def owner_full_name(self, obj): + o = obj.owner + if o: + return o.full_name + else: + return "" + + def get_readonly_fields(self, request, obj=None): + if obj: # editing an existing object + return self.readonly_fields + ('state',) + return self.readonly_fields + + +@admin.register(models.Notification) +class NotificationModelAdmin(admin.ModelAdmin): + + list_display = ["activity_description", "activity_type", "engagement_manual_id", + "vf_name", "is_sent", "is_read", "activity_create_time"] + list_filter = ["is_sent", "is_read"] + + def activity_description(self, obj): + return obj.activity.description + + def activity_type(self, obj): + return obj.activity.activity_type + + def activity_create_time(self, obj): + return obj.activity.create_time + + def engagement_manual_id(self, obj): + if obj.activity.engagement: + return obj.activity.engagement.engagement_manual_id + else: + return "" + + def vf_name(self, obj): + if obj.activity.engagement: + return models.VF.objects.get(engagement=obj.activity.engagement).name + else: + return "" + + +@admin.register(models.RecentEngagement) +class RecentEngagementModelAdmin(admin.ModelAdmin): + + list_display = ["engagement_manual_id", "vf_name", "ice_user", "action_type", "last_update"] + list_filter = ["action_type"] + + def vf_name(self, obj): + return obj.vf.name + + def engagement_manual_id(self, obj): + return obj.vf.engagement.engagement_manual_id + + def ice_user(self, obj): + return models.IceUserProfile.objects.get(uuid=obj.user_uuid).full_name + + +@admin.register(models.Role) +class RoleModelAdmin(admin.ModelAdmin): + + list_display = ["name"] + + +@admin.register(models.Vendor) +class VendorModelAdmin(admin.ModelAdmin): + + list_display = ["name", "public"] + list_editable = ["public"] + search_fields = ["name"] + + +@admin.register(models.VF) +class VFModelAdmin(admin.ModelAdmin): + + list_display = ["name", "deployment_target", "ecomp_release", "progress", "target_completion_date", + "target_lab_entry_date", "is_service_provider_internal", "git_repo_url", "engagement_stage", "engagement_manual_id"] + list_filter = ["deployment_target", "ecomp_release", "is_service_provider_internal", "vendor"] + list_editable = ["is_service_provider_internal"] + search_fields = ["name", "git_repo_url"] + + def engagement_manual_id(self, obj): + return obj.engagement.engagement_manual_id + + def progress(self, obj): + return obj.engagement.progress + + def target_completion_date(self, obj): + return obj.engagement.target_completion_date + + def engagement_stage(self, obj): + return obj.engagement.engagement_stage + + +@admin.register(models.VFC) +class VFCModelAdmin(admin.ModelAdmin): + + list_display = ["name", "external_ref_id", "ice_mandated", "vf_name", "company_name", "engagement_manual_id"] + list_filter = ["ice_mandated", "company"] + list_editable = ["external_ref_id", "ice_mandated"] + search_fields = ["name", "external_ref_id"] + + def vf_name(self, obj): + return obj.vf.name + + def engagement_manual_id(self, obj): + return obj.vf.engagement.engagement_manual_id + + def company_name(self, obj): + return obj.company.name diff --git a/django/engagementmanager/apps.py b/django/engagementmanager/apps.py new file mode 100755 index 0000000..e4a967d --- /dev/null +++ b/django/engagementmanager/apps.py @@ -0,0 +1,96 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.apps import AppConfig +from django.conf import settings +from engagementmanager.scheduled_jobs import ScheduledJobs +from engagementmanager.service.logging_service import LoggingServiceFactory + +cms_client = None +bus_service = None + + +class EngagementmanagerConfig(AppConfig): + name = 'engagementmanager' + verbose_name = "engagementmanager" + + def ready(self): + # This otherwise unused import causes the signal receivers + # to register themselves at the appropriate time. Do not remove. + import engagementmanager.vm_integration.em_api + ############################### + # Bootstrap Actions # + ############################### + from engagementmanager.utils.constants import Constants + logger = LoggingServiceFactory.get_logger() + + if (settings.DOMAIN == Constants.prodDomain): + logger.info("--Production Mode--") + else: + logger.info("--Development Mode--") + + from engagementmanager.cms_client.api import CMSClient + global cms_client + cms_client = CMSClient() + global bus_service + from engagementmanager.service.bus_service import BusService + bus_service = BusService() + self.__register_bus_service_handlers() + + ice_scheduler = ScheduledJobs(bus_service) + ice_scheduler.setup_daily_job() + ice_scheduler.setup_hourly_job() + + def __register_bus_service_handlers(self): + from engagementmanager.bus.messages.activity_event_message import ActivityEventMessage + from engagementmanager.bus.messages.daily_scheduled_message import DailyScheduledMessage + from engagementmanager.bus.messages.new_notification_message import NewNotificationMessage + from engagementmanager.bus.handlers.activity_event_handler import ActivityEventHandler + from engagementmanager.bus.handlers.daily_resend_notifications_handler import DailyResendNotificationsHandler + from engagementmanager.bus.handlers.digest_email_notification_handler import DigestEmailNotificationHandler + from engagementmanager.bus.handlers.new_notification_handler import NewNotificationHandler + from engagementmanager.bus.messages.hourly_scheduled_message import HourlyScheduledMessage + from engagementmanager.bus.handlers.check_news_and_announcements_handler import CheckNewsAndAnnouncementsHandler + from engagementmanager.bus.handlers.daily_notify_inactive_engagements_handler import DailyNotifyInactiveEngagementsHandler + + bus_service.register(ActivityEventHandler(), ActivityEventMessage) + bus_service.register(NewNotificationHandler(), NewNotificationMessage) + bus_service.register(DigestEmailNotificationHandler(), DailyScheduledMessage) + bus_service.register(DailyResendNotificationsHandler(), DailyScheduledMessage) + bus_service.register(DailyNotifyInactiveEngagementsHandler(), DailyScheduledMessage) + bus_service.register(CheckNewsAndAnnouncementsHandler(), HourlyScheduledMessage) diff --git a/django/engagementmanager/bus/__init__.py b/django/engagementmanager/bus/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/bus/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/bus/handlers/__init__.py b/django/engagementmanager/bus/handlers/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/bus/handlers/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/bus/handlers/activity_event_handler.py b/django/engagementmanager/bus/handlers/activity_event_handler.py new file mode 100755 index 0000000..d5ef819 --- /dev/null +++ b/django/engagementmanager/bus/handlers/activity_event_handler.py @@ -0,0 +1,52 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.bus.handlers.service_bus_base_handler import ServiceBusBaseHandler +from engagementmanager.service.activities_service import ActivitiesSvc +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class ActivityEventHandler(ServiceBusBaseHandler): + activities_service = ActivitiesSvc() + + def handle_message(self, bus_message): + logger.info("New ICE event from type '%s' arrived, activity will be generated." % + bus_message.activity_data.activity_type.name) + self.activities_service.generate_activity(bus_message.activity_data) diff --git a/django/engagementmanager/bus/handlers/check_news_and_announcements_handler.py b/django/engagementmanager/bus/handlers/check_news_and_announcements_handler.py new file mode 100755 index 0000000..6ef4fdb --- /dev/null +++ b/django/engagementmanager/bus/handlers/check_news_and_announcements_handler.py @@ -0,0 +1,49 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.bus.handlers.service_bus_base_handler import ServiceBusBaseHandler +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class CheckNewsAndAnnouncementsHandler(ServiceBusBaseHandler): + def handle_message(self, bus_message): + logger.debug("New hourly scheduled message arrived, will check for news and announcements and send notification" + " if needed.") + pass diff --git a/django/engagementmanager/bus/handlers/daily_notify_inactive_engagements.py b/django/engagementmanager/bus/handlers/daily_notify_inactive_engagements.py new file mode 100755 index 0000000..598b977 --- /dev/null +++ b/django/engagementmanager/bus/handlers/daily_notify_inactive_engagements.py @@ -0,0 +1,93 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.db.models.query_utils import Q +from django.utils import timezone +from django.utils.timezone import timedelta +from engagementmanager.bus.handlers.service_bus_base_handler import ServiceBusBaseHandler +from engagementmanager.models import Engagement, VF +from engagementmanager.service.activities_service import ActivitiesSvc +from engagementmanager.service.checklist_service import CheckListSvc +from engagementmanager.service.engagement_service import archive_engagement +from engagementmanager.utils.constants import EngagementStage +from engagementmanager.utils.activities_data import NoticeEmptyEngagementData +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class DailyNotifyInactiveEngagements(ServiceBusBaseHandler): + def handle_message(self, bus_message): + logger.debug("New digest bus message arrived - email is about to sent") + checklist_service = CheckListSvc() + engagements_list = Engagement.objects.filter(is_with_files=False, Q(engagement_stage=EngagementStage.Active.name) | Q(engagement_stage=EngagementStage.Intake.name)) + + for engagement in engagements_list: + files_found = checklist_service.getEngagementFiles(engagement.uuid) + if files_found: + engagement.is_with_files = True + engagement.save() + continue + + max_empty_time = self.get_max_empty_date(engagement.create_time) + + if max_empty_time < timezone.now(): + archive_engagement(engagement.uuid, "More than 30 days passed and no files added to gitlab yet") + else: + self.send_emails_logic(engagement) + + @staticmethod + def get_max_empty_date(creation_time): + return creation_time + timedelta(days=30) + + @staticmethod + def get_days_delta(start_time, end_time): + return (end_time - start_time).days + + def send_emails_logic(self, engagement): + + delta_days_from_creation = self.get_days_delta(engagement.create_time, timezone.now()) + alert_days = [7, 14, 21] + if (delta_days_from_creation in alert_days) or (delta_days_from_creation >= 23 and delta_days_from_creation < 30): + vf = VF.objects.get(engagement=engagement) + vf_name = vf.name + max_empty_time = self.get_max_empty_date(engagement.create_time).strftime('%b %d, %Y') + git_repo_url = vf.git_repo_url + activity_data = NoticeEmptyEngagementData( + vf_name, max_empty_time, git_repo_url, str(delta_days_from_creation), engagement) + ActivitiesSvc().generate_activity(activity_data) diff --git a/django/engagementmanager/bus/handlers/daily_notify_inactive_engagements_handler.py b/django/engagementmanager/bus/handlers/daily_notify_inactive_engagements_handler.py new file mode 100755 index 0000000..12acea1 --- /dev/null +++ b/django/engagementmanager/bus/handlers/daily_notify_inactive_engagements_handler.py @@ -0,0 +1,90 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.utils import timezone +from django.utils.timezone import timedelta +from engagementmanager.bus.handlers.service_bus_base_handler import ServiceBusBaseHandler +from engagementmanager.models import Engagement, VF +from engagementmanager.service.activities_service import ActivitiesSvc +from engagementmanager.service.checklist_service import CheckListSvc +from engagementmanager.service.engagement_service import archive_engagement +from engagementmanager.utils.constants import EngagementStage +from engagementmanager.utils.activities_data import NoticeEmptyEngagementData +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class DailyNotifyInactiveEngagementsHandler(ServiceBusBaseHandler): + def handle_message(self, bus_message): + logger.debug("New digest bus message arrived - email is about to sent") + checklist_service = CheckListSvc() + engagements_list = Engagement.objects.filter(is_with_files=False, engagement_stage=EngagementStage.Active.name) + + for engagement in engagements_list: + files_found = checklist_service.getEngagementFiles(engagement.uuid) + if files_found: + engagement.is_with_files = True + engagement.save() + continue + + max_empty_time = self.get_max_empty_date(engagement.create_time) + + if max_empty_time < timezone.now(): + archive_engagement(engagement.uuid, "More than 30 days passed and no files added to gitlab yet") + else: + self.send_emails_logic(engagement) + + def get_max_empty_date(self, creation_time): + return creation_time + timedelta(days=30) + + def get_days_delta(self, start_time, end_time): + return (end_time - start_time).days + + def send_emails_logic(self, engagement): + + delta_days_from_creation = self.get_days_delta(engagement.create_time, timezone.now()) + alert_days = [7, 14, 21] + if (delta_days_from_creation in alert_days) or (delta_days_from_creation >= 23 and delta_days_from_creation < 30): + vf = VF.objects.get(engagement=engagement) + vf_name = vf.name + max_empty_time = self.get_max_empty_date(engagement.create_time).strftime('%b %d, %Y') + git_repo_url = vf.git_repo_url + activity_data = NoticeEmptyEngagementData( + vf_name, max_empty_time, git_repo_url, str(delta_days_from_creation), engagement) + ActivitiesSvc().generate_activity(activity_data) diff --git a/django/engagementmanager/bus/handlers/daily_resend_notifications_handler.py b/django/engagementmanager/bus/handlers/daily_resend_notifications_handler.py new file mode 100755 index 0000000..9919cad --- /dev/null +++ b/django/engagementmanager/bus/handlers/daily_resend_notifications_handler.py @@ -0,0 +1,75 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from django.template.loader import get_template +from engagementmanager import mail +from engagementmanager.bus.handlers.service_bus_base_handler import ServiceBusBaseHandler +from engagementmanager.mail import sendMail +from engagementmanager.models import Notification +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class DailyResendNotificationsHandler(ServiceBusBaseHandler): + def handle_message(self, bus_message): + logger.debug("New resend notifications message arrived - emails is about to sent to the " + "all unsent notifications") + unsent_notifications = Notification.objects.filter(is_sent=False) + for notification in unsent_notifications: + if notification.user.email_updates_on_every_notification: + try: + subject_template = get_template("{notification_template_dir}notification_mail_subject.html".format( + notification_template_dir=Constants.notification_template_dir)) + msg_template = get_template("{notification_template_dir}notification_mail_body.html".format( + notification_template_dir=Constants.notification_template_dir)) + + sendMail(notification.user.email, json.loads(notification.activity.metadata), + msg_template, subject_template, mail_from=mail.ice_admin_mail_from) + notification.is_sent = True + notification.save() + except Exception as e: + msg = "Something went wrong while trying to resend bulk mail " \ + "as part of the notifications daily resend" + logger.error(msg + " " + e) + else: + notification.is_sent = True + notification.save() + logger.info("User choose not to get email on every notification, set it as sent.") diff --git a/django/engagementmanager/bus/handlers/digest_email_notification_handler.py b/django/engagementmanager/bus/handlers/digest_email_notification_handler.py new file mode 100755 index 0000000..7f5cb6b --- /dev/null +++ b/django/engagementmanager/bus/handlers/digest_email_notification_handler.py @@ -0,0 +1,74 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from datetime import datetime +from django.template.loader import get_template +from engagementmanager import mail +from engagementmanager.bus.handlers.service_bus_base_handler import ServiceBusBaseHandler +from engagementmanager.mail import sendMail +from engagementmanager.models import Notification, IceUserProfile +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class DigestEmailNotificationHandler(ServiceBusBaseHandler): + def handle_message(self, bus_message): + logger.debug("New digest bus message arrived - email is about to sent") + today = datetime.now().date() + users = Notification.objects.filter(activity__create_time__gte=today).values("user").distinct() + + for user in users: + user = IceUserProfile.objects.get(id=user['user']) + + if user.email_updates_daily_digest: + notifications = Notification.objects.filter(activity__create_time__gte=today, user=user) + try: + subject_template = get_template("{notification_template_dir}" + "notification_digest_mail_subject.html".format( + notification_template_dir=Constants.notification_template_dir)) + msg_template = get_template("{notification_template_dir}" + "notification_digest_mail_body.html".format( + notification_template_dir=Constants.notification_template_dir)) + + sendMail(user.email, notifications.values(), + msg_template, subject_template, mail_from=mail.ice_admin_mail_from) + except Exception as e: + msg = "Something went wrong while trying to send bulk mail as part of the digest notifications" + logger.error(msg) diff --git a/django/engagementmanager/bus/handlers/new_notification_handler.py b/django/engagementmanager/bus/handlers/new_notification_handler.py new file mode 100755 index 0000000..00491fa --- /dev/null +++ b/django/engagementmanager/bus/handlers/new_notification_handler.py @@ -0,0 +1,74 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from engagementmanager import mail +from engagementmanager.bus.handlers.service_bus_base_handler import ServiceBusBaseHandler +from django.template.loader import get_template +from engagementmanager.mail import sendMail +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + + +logger = LoggingServiceFactory.get_logger() + + +class NewNotificationHandler(ServiceBusBaseHandler): + def handle_message(self, bus_message): + logger.info("New notification (%s) arrived - email will sent" % + bus_message.notification.uuid) + + user = bus_message.notification.user + if user.email_updates_on_every_notification: + try: + subject_template = get_template("{notification_template_dir}notification_mail_subject.html".format( + notification_template_dir=Constants.notification_template_dir)) + msg_template = get_template("{notification_template_dir}notification_mail_body.html".format( + notification_template_dir=Constants.notification_template_dir)) + + sendMail(user.email, json.loads(bus_message.notification.activity.metadata), + msg_template, subject_template, mail_from=mail.ice_admin_mail_from) + bus_message.notification.is_sent = True + bus_message.notification.save() + except Exception as e: + msg = "Something went wrong while trying to send bulk mail as part of the notification" + logger.error(msg + " " + str(e)) + else: + bus_message.notification.is_sent = True + bus_message.notification.save() + logger.info("User choose not to get email on every notification, set it as sent.") diff --git a/django/engagementmanager/bus/handlers/service_bus_base_handler.py b/django/engagementmanager/bus/handlers/service_bus_base_handler.py new file mode 100755 index 0000000..7b4a83b --- /dev/null +++ b/django/engagementmanager/bus/handlers/service_bus_base_handler.py @@ -0,0 +1,54 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from abc import ABCMeta, abstractmethod + +from engagementmanager.bus.messages.service_bus_base_message import ServiceBusBaseMessage +from engagementmanager.utils.vvp_exceptions import VvpGeneralException + + +class ServiceBusBaseHandler: + __metaclass__ = ABCMeta + + def validate_message(self, bus_message): + if not issubclass(type(bus_message), ServiceBusBaseMessage): + raise VvpGeneralException("You can't handle message which is not from type of ServiceBusBaseMessage") + + @abstractmethod + def handle_message(self, bus_message): + pass diff --git a/django/engagementmanager/bus/messages/__init__.py b/django/engagementmanager/bus/messages/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/bus/messages/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/bus/messages/activity_event_message.py b/django/engagementmanager/bus/messages/activity_event_message.py new file mode 100755 index 0000000..67bf319 --- /dev/null +++ b/django/engagementmanager/bus/messages/activity_event_message.py @@ -0,0 +1,49 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.bus.messages.service_bus_base_message import ServiceBusBaseMessage +from engagementmanager.utils.activities_data import ActivityData +from engagementmanager.utils.vvp_exceptions import VvpGeneralException + + +class ActivityEventMessage(ServiceBusBaseMessage): + def __init__(self, activity_data): + if not issubclass(type(activity_data), ActivityData): + raise VvpGeneralException("Activity data can be from type ActivityData only.") + + self.activity_data = activity_data diff --git a/django/engagementmanager/bus/messages/daily_scheduled_message.py b/django/engagementmanager/bus/messages/daily_scheduled_message.py new file mode 100755 index 0000000..41941e8 --- /dev/null +++ b/django/engagementmanager/bus/messages/daily_scheduled_message.py @@ -0,0 +1,44 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.bus.messages.service_bus_base_message import ServiceBusBaseMessage + + +class DailyScheduledMessage(ServiceBusBaseMessage): + def __init__(self): + pass diff --git a/django/engagementmanager/bus/messages/hourly_scheduled_message.py b/django/engagementmanager/bus/messages/hourly_scheduled_message.py new file mode 100755 index 0000000..8c733bf --- /dev/null +++ b/django/engagementmanager/bus/messages/hourly_scheduled_message.py @@ -0,0 +1,44 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.bus.messages.service_bus_base_message import ServiceBusBaseMessage + + +class HourlyScheduledMessage(ServiceBusBaseMessage): + def __init__(self): + pass diff --git a/django/engagementmanager/bus/messages/new_notification_message.py b/django/engagementmanager/bus/messages/new_notification_message.py new file mode 100755 index 0000000..ce4ce06 --- /dev/null +++ b/django/engagementmanager/bus/messages/new_notification_message.py @@ -0,0 +1,49 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.bus.messages.service_bus_base_message import ServiceBusBaseMessage +from engagementmanager.models import Notification +from engagementmanager.utils.vvp_exceptions import VvpGeneralException + + +class NewNotificationMessage(ServiceBusBaseMessage): + def __init__(self, notification): + if type(notification) is not Notification: + raise VvpGeneralException("New notification event can be from type Notification only.") + + self.notification = notification diff --git a/django/engagementmanager/bus/messages/service_bus_base_message.py b/django/engagementmanager/bus/messages/service_bus_base_message.py new file mode 100755 index 0000000..3f97a0d --- /dev/null +++ b/django/engagementmanager/bus/messages/service_bus_base_message.py @@ -0,0 +1,46 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from abc import ABCMeta + + +class ServiceBusBaseMessage: + __metaclass__ = ABCMeta + + def __init__(self): + pass diff --git a/django/engagementmanager/cms_client/__init__.py b/django/engagementmanager/cms_client/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/cms_client/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/cms_client/api.py b/django/engagementmanager/cms_client/api.py new file mode 100755 index 0000000..a0ca5b1 --- /dev/null +++ b/django/engagementmanager/cms_client/api.py @@ -0,0 +1,159 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from django.conf import settings +from oauthlib.oauth2 import BackendApplicationClient, TokenExpiredError +from requests_oauthlib import OAuth2Session +from rest_framework.status import HTTP_401_UNAUTHORIZED +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class CMSClient(object): + """ + ICE CMS (Mezzanine) API Client SDK + """ + + def __init__(self): + """ + Ice CMS client constructor -> + :param MZN_ID: from env vars. + :param MZN_Secret: from env vars. + """ + super(CMSClient, self).__init__() + + self.client_id = settings.CMS_APP_CLIENT_ID + self.client_secret = settings.CMS_APP_CLIENT_SECRET + self.api_url = settings.CMS_URL + self.token = self.generateToken(self.client_id, self.client_secret) + self.session = OAuth2Session(self.client_id, token=self.token) + + # PROBLEM TO REMOVE TRY AND CATCH + def generateToken(self, client_id, client_secret): + """ + Create oauth2 token by id and secret (via cms server) + :param client_id: client id (from env vars) + :param client_secret: client secret (from env vars) + :return: return the result token. + """ + token = None + + try: + client = BackendApplicationClient(client_id=client_id) + oatuh = OAuth2Session(client=client) + token = oatuh.fetch_token(token_url=self.api_url + 'oauth2/token/', client_id=client_id, + client_secret=client_secret) + except Exception as exception: + logger.error( + 'Could not create CMS token, error message: ' + str(exception)) + + return token + + @staticmethod + def json_serialize(obj): + """ + Returns JSON serialization of object + """ + return json.dumps(obj) + + @staticmethod + def json_deserialize(string): + """ + Returns deserialization of JSON + """ + return json.loads(string) + + def get(self, resource, params=None): + """ + Make a GET HTTP request + """ + response = None + try: + response = self.session.get(self.api_url + resource, params=params) + if response.status_code == HTTP_401_UNAUTHORIZED: + logger.error('Token expired (401 status excepted), will renew cms token now') + self.__init__() + response = self.session.get(self.api_url + resource, params=params) + except TokenExpiredError as exception: + logger.error('Token expired (TokenExpiredError exception excepted),' + ' will renew cms token now: ' + str(exception)) + self.__init__() + response = self.session.get(self.api_url + resource, params=params) + item = self.json_deserialize(response.content.decode('utf-8')) + return item + + def get_posts(self, offset=0, limit=10, category="", date_min=""): + """ + Get published blog posts + :param date_min: all the posts returned will be after this date + :param offset: pagination offset + :param limit: pagination limit + :param category: the category which the post related to + :param limit: date_min of posts to return + :return: list of dicts for most recently published blog posts + """ + return self.get('posts?offset={}&limit={}&category_name={}&date_min={}'.format(int(offset), int(limit), + category, date_min))['results'] + + def get_pages(self, title=""): + """ + Get all pages and it's children. + :param title: The title of the page we want + :return: list of pages by out filters declaration + """ + return self.get('pages?title={}'.format(title))['results'] + + def get_page(self, id): + """ + Return specific page by id + :param id: The id of the page we want to require + :return: the page result + """ + return self.get('pages/{}'.format(int(id))) + + def search_pages(self, keyword): + """ + Return pages by keyword contained in title or content + :param keyword: The keyword which will be searched in title and content + :return: the pages as result + """ + + return self.get('pages/search/?keyword={}'.format(keyword)) diff --git a/django/engagementmanager/decorator/__init__.py b/django/engagementmanager/decorator/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/decorator/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/decorator/auth.py b/django/engagementmanager/decorator/auth.py new file mode 100755 index 0000000..686a8cc --- /dev/null +++ b/django/engagementmanager/decorator/auth.py @@ -0,0 +1,103 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import traceback +import bleach +from rest_framework import status +from rest_framework.response import Response +from rest_framework.status import HTTP_401_UNAUTHORIZED, \ + HTTP_400_BAD_REQUEST, HTTP_500_INTERNAL_SERVER_ERROR +from engagementmanager.service.authorization_service import AuthorizationService +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def auth(action, is_internal=False): + """ + Check that given action is permitted by the user + """ + def _dec(func): + def _new_func(*args, **kwargs): + auth_service = AuthorizationService() + + # Extract USER - A MUST Have in KWARGS # + user = request_data_mgr.get_user() + if user == None: + msg = "user couldn't be identified in the request" + logger.error(msg) + if (is_internal == True): + return msg, HTTP_400_BAD_REQUEST + return Response(msg, status=status.HTTP_400_BAD_REQUEST) + + checklist_uuid = request_data_mgr.get_cl_uuid() + eng_uuid = request_data_mgr.get_eng_uuid() + + try: + result = None + message = None + result, message = auth_service.is_user_able_to(user, action, eng_uuid, checklist_uuid) + logger.debug('Authorization Service : ' + action.name + + '. Result=' + str(result) + '. message=' + str(message)) + if result == False: + msg = "User not authorized: " + \ + str(user.uuid) + ". eng_uuid=" + str(eng_uuid) + ". checklist_uuid=" + str(checklist_uuid) + if (is_internal == True): + return msg, HTTP_401_UNAUTHORIZED + msg = bleach.clean(msg, tags=['a', 'b']) + return Response(msg, status=status.HTTP_401_UNAUTHORIZED) + + except Exception as e: + logger.error("=====================Exception=====================") + msg = "A problem occurred while trying to authorize user.uuid= " + \ + str(user.uuid) + ". eng_uuid=" + str(eng_uuid) + \ + ". checklist_uuid=" + str(checklist_uuid) + "action=" + str(action) + logger.error(str(e) + " Message: " + msg) + logger.error(traceback.format_exc()) + logger.error("===================================================") + + if (is_internal == True): + return msg, HTTP_500_INTERNAL_SERVER_ERROR + msg = "Action was failed to be performed" + return Response(msg, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + return func(*args, **kwargs) + + return _new_func + + return _dec diff --git a/django/engagementmanager/decorator/class_decorator.py b/django/engagementmanager/decorator/class_decorator.py new file mode 100755 index 0000000..362e473 --- /dev/null +++ b/django/engagementmanager/decorator/class_decorator.py @@ -0,0 +1,47 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +def classDecorator(decorators): + def decorate(cls): + for attr in cls.__dict__: + if callable(getattr(cls, attr)): + for ice_decorator in decorators: + if (attr in ["get", "put", "post", "delete", "entity_list", "entity_detail", "set_attr"]): + setattr(cls, attr, ice_decorator(getattr(cls, attr))) + return cls + return decorate diff --git a/django/engagementmanager/decorator/log_func_entry.py b/django/engagementmanager/decorator/log_func_entry.py new file mode 100755 index 0000000..1e7d840 --- /dev/null +++ b/django/engagementmanager/decorator/log_func_entry.py @@ -0,0 +1,50 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from functools import wraps +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def logFuncEntry(func): + @wraps(func) + def log(*args, **kwargs): + logger.debug('calling {}'.format(func.__name__) + " | " + str(args) + " | " + str(kwargs)) + return func(*args, **kwargs) + return log diff --git a/django/engagementmanager/decorator/retry.py b/django/engagementmanager/decorator/retry.py new file mode 100755 index 0000000..d0c15c1 --- /dev/null +++ b/django/engagementmanager/decorator/retry.py @@ -0,0 +1,52 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +"""This module provides retry_connection, a simple wrapper around retrying.retry, for our most +common use case. + +""" + +from requests.exceptions import Timeout, ConnectionError +from retrying import retry + + +def is_connection_exception(exception): + return isinstance(exception, (ConnectionError, Timeout)) + + +retry_connection = retry(stop_max_attempt_number=2, retry_on_exception=is_connection_exception) diff --git a/django/engagementmanager/git/__init__.py b/django/engagementmanager/git/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/git/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/git/git_manager.py b/django/engagementmanager/git/git_manager.py new file mode 100755 index 0000000..4bc8de0 --- /dev/null +++ b/django/engagementmanager/git/git_manager.py @@ -0,0 +1,52 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.models import VF +from engagementmanager.vm_integration.vm_client import \ + send_get_list_of_repo_files_event +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + +class GitManager(object): + def getRepoAssociatedFilesForUser(self, eng_uuid): + logger.debug("Fetching the repo associated files for engagement " + + eng_uuid) + vf = VF.objects.get(engagement__uuid=eng_uuid) + fileList = send_get_list_of_repo_files_event(vf) + return fileList diff --git a/django/engagementmanager/http_client.py b/django/engagementmanager/http_client.py new file mode 100755 index 0000000..c4c8afd --- /dev/null +++ b/django/engagementmanager/http_client.py @@ -0,0 +1,54 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from http.client import HTTPSConnection + + +class HttpClient(HTTPSConnection): + ''' + classdocs + ''' + + def __init__(self, protocol, host, port, params=None): + if (protocol == 'HTTP'): + self.conn = self.HTTPConnection(host, port) + else: # SSL + self.conn = HTTPSConnection(host, port) + + def getConn(self): + return self.conn diff --git a/django/engagementmanager/mail.py b/django/engagementmanager/mail.py new file mode 100755 index 0000000..10279b9 --- /dev/null +++ b/django/engagementmanager/mail.py @@ -0,0 +1,71 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.conf import settings +from django.core.mail import send_mail, send_mass_mail + +from engagementmanager.service.logging_service import LoggingServiceFactory +from engagementmanager.utils.constants import TemplatesConstants + +ice_admin_mail_from = settings.CONTACT_FROM_ADDRESS + +logger = LoggingServiceFactory.get_logger() + + +def sendMail(email, data, mail_body_template, mail_subject_template, mail_from=ice_admin_mail_from): + logger.debug("about to send mail to " + email) + if data is None: + data = {} + data.update(TemplatesConstants.context) + html_msg = mail_body_template.render(context=data) + mail_subject = mail_subject_template.render(context=data) + # send mail with template + send_mail(mail_subject, '', "D2 ICE Team <" + mail_from + ">", [email], fail_silently=False, html_message=html_msg) + logger.debug("Looks like email delivery to " + email + " has succeeded") + + +def sendBulkMail(datatuple): + logger.debug("about to send mail") + + try: + num_sent = send_mass_mail(datatuple) + logger.debug("Looks like email delivery has succeeded. Number of sent mails is " + str(num_sent)) + return num_sent + except Exception as e: # Dont remove try-except since it is invoked from Notification Bot + logger.error("Email delivery has failed. Error is: " + str(e)) + raise e diff --git a/django/engagementmanager/management/__init__.py b/django/engagementmanager/management/__init__.py new file mode 100755 index 0000000..36beacd --- /dev/null +++ b/django/engagementmanager/management/__init__.py @@ -0,0 +1,39 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. + diff --git a/django/engagementmanager/management/commands/__init__.py b/django/engagementmanager/management/commands/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/management/commands/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/management/commands/clean_gitlab_content.py b/django/engagementmanager/management/commands/clean_gitlab_content.py new file mode 100755 index 0000000..5299367 --- /dev/null +++ b/django/engagementmanager/management/commands/clean_gitlab_content.py @@ -0,0 +1,103 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +""" clean_gitlab_content +Will delete content from gitlab to create initial environment: +1.Projects +2.Groups +3.Users + +This command uses gitlab client rest api to remove data. +This command is part of clean_vvp_system command but can be used separately as well. + +WARNING: It will delete almost everything, if you have necessary data DO NOT USE THIS COMMAND! +""" +from django.conf import settings +from django.core.management.base import BaseCommand +import requests +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class Command(BaseCommand): + def handle(self, *args, **options): + logger.info("***************************************") + logger.info(">>git-lab is about to be cleaned up!") + logger.info("***************************************") + + entities = ['projects', 'groups', 'users', ] + headers = dict() + headers['Content-type'] = 'application/json' + headers['PRIVATE-TOKEN'] = settings.GITLAB_TOKEN + + for entity in entities: + entities_deleted = [] + gitlab_entity_url = settings.GITLAB_URL + "api/v3/%s/" % entity + r1 = requests.get(gitlab_entity_url, headers=headers, verify=False) + data = r1.json() + + while len(data) > 1: + for record in data: + try: + if record['id'] not in entities_deleted \ + and record['name'] != 'Administrator': + r2 = requests.delete(gitlab_entity_url + + str(record['id']), + headers=headers, verify=False) + logger.info("Entity '%s' with id %s Will be deleted" + " in a bit (type: %s)" % ( + record['name'], + record['id'], entity,)) + + entities_deleted.append(record['id']) + except Exception as e: + logger.error("Some problem occurred... We give it " + "another shot...", e) + + r1 = requests.get(gitlab_entity_url, headers=headers, + verify=False) + data = r1.json() + + logger.info("***************************************") + logger.info(">>>>All %s deleted from git-lab" % entity) + logger.info("***************************************") + + logger.info("***************************************") + logger.info(">>git-lab is now clean!") + logger.info("***************************************") diff --git a/django/engagementmanager/management/commands/clean_jenkins_jobs.py b/django/engagementmanager/management/commands/clean_jenkins_jobs.py new file mode 100755 index 0000000..c19f28d --- /dev/null +++ b/django/engagementmanager/management/commands/clean_jenkins_jobs.py @@ -0,0 +1,73 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +""" clean_jenkins_jobs +Will delete content(jobs) from jenkins to create initial environment. + +This command uses jenkins_client api to remove data. +This command is part of clean_vvp_system command but can be used separately as well. + +WARNING: It will delete almost everything, if you have necessary data DO NOT USE THIS COMMAND! +""" +from validationmanager.utils.clients import get_jenkins_client +from django.core.management.base import BaseCommand +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class Command(BaseCommand): + def handle(self, *args, **options): + logger.info("***************************************") + logger.info(">>Jenkins is about to be cleaned up!") + logger.info("***************************************") + + try: + jenkins_client = get_jenkins_client() + job_names = jenkins_client.get_jobs_names() + + for job_name in job_names: + jenkins_client.delete_job(job_name) + logger.info("Jenkins job '%s' deleted successfully." % job_name) + except Exception as e: + logger.error("Some problem occurred while trying " + "cleaning Jenkins...", e) + + logger.info("***************************************") + logger.info(">>Jenkins is now clean!") + logger.info("***************************************") diff --git a/django/engagementmanager/management/commands/clean_vvp_db.py b/django/engagementmanager/management/commands/clean_vvp_db.py new file mode 100755 index 0000000..931f684 --- /dev/null +++ b/django/engagementmanager/management/commands/clean_vvp_db.py @@ -0,0 +1,96 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +""" clean_vvp_db +Will delete content from database (almost all entities) to create initial environment. + +This command uses django orm to remove data. +This command is part of clean_vvp_system command but can be used separately as well. + +WARNING: It will delete almost everything, if you have necessary data DO NOT USE THIS COMMAND! +""" +from django.core.management.base import BaseCommand +from engagementmanager import models +from engagementmanager.management.commands.initial_populate_db import admin_dummy_users, admin_ro_dummy_users, \ + dummy_users, el_dummy_users +from engagementmanager.service.logging_service import LoggingServiceFactory +from engagementmanager.utils.constants import Constants + +logger = LoggingServiceFactory.get_logger() + + +class Command(BaseCommand): + def handle(self, *args, **options): + logger.info("***************************************") + logger.info(">>%s db is about to be cleaned up!" % Constants.program_name) + logger.info("***************************************") + + excluded_emails = [dummy_users[0][1], dummy_users[1][1], + el_dummy_users[0][1], el_dummy_users[1][1], + admin_dummy_users[0][1], admin_ro_dummy_users[0][1], ] + + try: + models.EngagementStatus.objects.all().delete() + models.Invitation.objects.all().delete() + models.Notification.objects.all().delete() + models.Activity.objects.all().delete() + models.NextStep.objects.all().delete() + models.ChecklistAuditLog.objects.all().delete() + models.ChecklistDecision.objects.all().delete() + models.Checklist.objects.all().delete() + models.ChecklistLineItem.objects.all().delete() + models.ChecklistSection.objects.all().delete() + models.ChecklistTemplate.objects.all().delete() + models.RecentEngagement.objects.all().delete() + models.VFC.objects.all().delete() + models.VF.objects.all().delete() + models.EngagementStatus.objects.all().delete() + models.Engagement.objects.all().delete() + models.IceUserProfile.objects.exclude(email__in=excluded_emails)\ + .delete() + models.CustomUser.objects.exclude(user_ptr_id__in=models.IceUserProfile.objects.all().values('id')).delete() + + models.DeploymentTarget.objects.all().delete() + models.DeploymentTargetSite.objects.all().delete() + models.ECOMPRelease.objects.all().delete() + logger.info("***************************************") + logger.info(">>%s db is now clean!" % Constants.program_name) + logger.info("***************************************") + except Exception as exception: + logger.error("Something went wrong while trying" + " to clean %s db" % Constants.program_name, exception) diff --git a/django/engagementmanager/management/commands/clean_vvp_system.py b/django/engagementmanager/management/commands/clean_vvp_system.py new file mode 100755 index 0000000..a86f770 --- /dev/null +++ b/django/engagementmanager/management/commands/clean_vvp_system.py @@ -0,0 +1,93 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +""" clean_vvp_system +Will clean all program data: +1. Deletes all gitlab projects/users/groups. +2. Deletes all data stored in database. +3. Deletes all jobs stored in jenkins. + +It's recommended to clean the vvp system if you desire in a fresh copy of the vvp program +without installing it all over again. + +WARNING: It will delete almost everything, if you have necessary data DO NOT USE THIS COMMAND! +""" +from django.core.management.base import BaseCommand +from engagementmanager.management.commands import clean_gitlab_content +from engagementmanager.management.commands import clean_jenkins_jobs +from engagementmanager.management.commands import clean_vvp_db +from engagementmanager.management.commands import initial_populate_db +from engagementmanager.service.logging_service import LoggingServiceFactory +from engagementmanager.utils.constants import Constants + +logger = LoggingServiceFactory.get_logger() + + +class Command(BaseCommand): + def handle(self, *args, **options): + logger.info("***************************************") + logger.info("%s system is about to be cleaned up!" % Constants.program_name) + logger.info("***************************************") + + try: + clean_gitlab_content_command = clean_gitlab_content.Command() + clean_gitlab_content_command.handle(args, options) + except Exception as e: + logger.error("There was a problem cleaning git-lab", e) + + try: + clean_jenkins_jobs_command = clean_jenkins_jobs.Command() + clean_jenkins_jobs_command.handle(args, options) + except Exception as e: + logger.error("There was a problem cleaning Jenkins", e) + + try: + clean_vvp_db_command = clean_vvp_db.Command() + clean_vvp_db_command.handle(args, options) + except Exception as e: + logger.error("There was a problem cleaning %s db" % Constants.program_name, e) + + try: + initial_populate_db_command = initial_populate_db.Command() + initial_populate_db_command.handle(args, options) + except Exception as e: + logger.error("There was a problem populate %s db after cleaning" % Constants.program_name, e) + + logger.info("***************************************") + logger.info("Done!") + logger.info("***************************************") diff --git a/django/engagementmanager/management/commands/initial_populate_db.py b/django/engagementmanager/management/commands/initial_populate_db.py new file mode 100755 index 0000000..a0ca177 --- /dev/null +++ b/django/engagementmanager/management/commands/initial_populate_db.py @@ -0,0 +1,912 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +""" intial_populate_db +Will create initial content to use this system. + +This command is creating users, templates, companies, deployment targets, sites and much more. +Will run at the state of a clean system so it won't cause data collisions. + +WARNING: Do not run while there is data at the system. +""" +import inspect +import random +from django.conf import settings +from django.core.management.base import BaseCommand +from django.utils import timezone +from engagementmanager.models import Role, Vendor, IceUserProfile, DeploymentTarget, \ + DeploymentTargetSite, Checklist, ChecklistDecision, ChecklistLineItem, \ + ChecklistTemplate, ChecklistSection, ECOMPRelease, Engagement, \ + CustomUser +from engagementmanager.models import VF +from engagementmanager.serializers import ThinVFModelSerializer +from engagementmanager.utils.constants import Roles, Constants +from engagementmanager.utils.validator import logEncoding +from engagementmanager.views_helper import createUserTemplate +from validationmanager.models import ValidationTest +from uuid import uuid4 +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class Command(BaseCommand): + + def handle(self, *args, **options): + if (settings.ENVIRONMENT == "local" or settings.ENVIRONMENT == "development"): + execute_bootstrap_actions() + + +companies = [ + 'Affirmed Networks', + 'Amdocs', + 'Brocade', + 'Ciena', + 'Cisco', + 'Ericsson', + 'Fujitsu', + 'Juniper', + 'Metaswitch', + 'Nokia' +] + +companies_not_public = [ + 'Adtran', + 'Velocloud', + 'Spirent', + 'Mitel', +] + +admin_dummy_users = [['admin bogus user', Constants.service_provider_admin_mail, '+1-23-456-78901']] + +admin_ro_dummy_users = [ + ['ro admin bogus user', Constants.service_provider_admin_ro_mail, '+1-23-456-78901']] + +dummy_users = [ + ['Bugs Bunny', 'bb@' + Constants.service_provider_mail_domain[0], '+1-404-986-9624'], + ['CI Standard 1', 'ci_standard_1@' + Constants.service_provider_mail_domain[0], '+1-404-986-9624'], +] + +el_dummy_users = [ + ['Donald Duck', 'dd1122@' + Constants.service_provider_mail_domain[0], '+1-404-986-9624'], + ['Homer Simpson', 'hs0007@' + Constants.service_provider_mail_domain[0], '+1-425-281-3547'] +] + +checklist_templates = [ + { + 'name': 'Heat Templates', + 'category': 'heat', + 'version': 1, + 'sections': [ + { + 'name': 'Basic Heat Format and Syntax', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Filenames', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Valid YAML and HEAT', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + } + ] + }, + { + 'name': 'Parameter And Resource Specification', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Parameters', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Resources', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Unique Names for Resources', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Outputs', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + } + ] + + }, + { + 'name': 'Naming Conventions', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Name, Flavor, and Image Assignments', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Availability Zones', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Required Metadata', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Optional Metadata', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Volumes', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Keys and Keypairs', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Networks', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Subnet', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Fixed IPs', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Allowed Address Pairs', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Ports', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + } + ] + + }, + { + 'name': 'General Guidelines', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'HEAT Files Support (get_file)', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'HTTP-based references', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Anti-Affinity and Affinity Rules', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Resource Data Synchronization', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + } + ] + + } + ] + }, + { + 'name': 'Image Validation', + 'category': 'glance', + 'version': 1, + 'sections': [ + { + 'name': 'Prerequisites', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Image Source', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Vendor Provided Image', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + } + ] + }, + { + 'name': 'Image Scan', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Clam AV Scan', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + ] + }, + ] + }, + { + 'name': 'AIC Instantiation', + 'category': 'instantiation', + 'version': 1, + 'sections': [ + { + 'name': 'Prerequisites', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Validated Heat Template(s)', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Validated Glance Image(s)', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + } + ] + }, + { + 'name': 'Manual Instantiation in AIC', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Create the HEAT Stack', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Delete the HEAT Stack', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + } + ] + } + ] + }, + { + 'name': 'ASDC Onboarding', + 'category': 'asdc', + 'version': 1, + 'sections': [ + { + 'name': 'Prerequisites', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Validated Heat Template(s)', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Validated Glance Image(s)', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'Successful Manual Instantiation', + 'weight': 1, + 'description': 'Description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + } + ] + }, + { + 'name': 'Onboard The VNF To The Target ASDC Environment', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'validation instructions', + 'line_items': [ + { + 'name': 'Create the VNF', + 'weight': 1, + 'description': 'description', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + ] + }, + ] + } +] + +# Map all the validation tests to the right line items +# +# Get the validation test mappings like this from a reference deployment: +# from validationmanager.models import ValidationTest +# vts = sorted(ValidationTest.objects.all(), key=lambda vt: vt.name) +# for vt in vts: +# for li in vt.line_items.all(): +# print("['" + vt.name + "', '" + li.name + "'],") +validation_tests = [ + ['test_all_nested_templates_provided', 'Filenames'], + ['test_all_referenced_resources_exists', 'Resources'], + ['test_allowed_address_pairs_format', 'Allowed Address Pairs'], + ['test_allowed_address_pairs_format', 'Ports'], + ['test_allowed_address_pairs_include_vm_type_network_role', 'Ports'], + ['test_allowed_address_pairs_include_vm_type_network_role', 'Ports'], + ['test_alphanumeric_resource_ids_only', 'Resources'], + ['test_availability_zone_naming', 'Availability Zones'], + ['test_availability_zone_naming_use_get_param', 'Availability Zones'], + ['test_base_template_names', 'Filenames'], + ['test_base_template_outputs_consumed', 'Outputs'], + ['test_default_values', 'Parameters'], + ['test_env_and_yaml_same_name', 'Filenames'], + ['test_env_files_provided', 'Filenames'], + ['test_environment_file_contains_required_sections', 'Valid YAML and HEAT'], + ['test_environment_file_extension', 'Filenames'], + ['test_environment_file_sections_have_the_right_format', 'Valid YAML and HEAT'], + ['test_environment_structure', 'Valid YAML and HEAT'], + ['test_fixed_ips_format', 'Fixed IPs'], + ['test_fixed_ips_format', 'Ports'], + ['test_fixed_ips_format_use_get_parm', 'Fixed IPs'], + ['test_fixed_ips_format_use_get_parm', 'Ports'], + ['test_fixed_ips_include_vm_type_network_role', 'Ports'], + ['test_fixed_ips_include_vm_type_network_role', 'Ports'], + ['test_get_file_only_reference_local_files', 'HEAT Files Support (get_file)'], + ['test_heat_pairs_provided', 'Filenames'], + ['test_heat_template_file_extension', 'Filenames'], + ['test_heat_template_parameters_contain_required_fields', 'Valid YAML and HEAT'], + ['test_heat_template_structure', 'Valid YAML and HEAT'], + ['test_heat_template_structure_contains_required_sections', 'Valid YAML and HEAT'], + ['test_heat_template_structure_sections_have_the_right_format', 'Valid YAML and HEAT'], + ['test_heat_templates_provided', 'Filenames'], + ['test_network_format', 'Networks'], + ['test_network_format', 'Ports'], + ['test_network_format_use_get_param_or_get_resource', 'Networks'], + ['test_network_format_use_get_param_or_get_resource', 'Ports'], + ['test_no_unused_parameters_between_env_and_templates', 'Parameters'], + ['test_nova_servers_correct_parameter_types', 'Name, Flavor, and Image Assignments'], + ['test_nova_servers_valid_resource_ids', 'Resources'], + ['test_numeric_parameter', 'Parameters'], + ['test_parameter_valid_keys', 'Valid YAML and HEAT'], + ['test_parameter_valid_keys', 'Parameters'], + ['test_parse_yaml', 'Valid YAML and HEAT'], + ['test_port_resource_ids', 'Resources'], + ['test_port_resource_ids', 'Ports'], + ['test_referenced_and_defined_parameters_match', 'Parameters'], + ['test_required_parameters_no_constraints', 'Required Metadata'], + ['test_required_parameters_provided_in_env_file', 'Required Metadata'], + ['test_required_parameters_provided_in_heat_template', 'Required Metadata'], + ['test_required_parameters_provided_in_heat_template', 'Required Metadata'], + ['test_servers_have_optional_metadata', 'Optional Metadata'], + ['test_servers_have_required_metadata', 'Required Metadata'], + ['test_servers_metadata_use_get_param', 'Required Metadata'], + ['test_subnet_format', 'Subnet'], + ['test_subnet_format', 'Ports'], + ['test_subnet_format_use_get_param_or_get_resource', 'Subnet'], + ['test_subnet_format_use_get_param_or_get_resource', 'Ports'], + ['test_unique_name_resources', 'Unique Names for Resources'], + ['test_unique_name_str_replace_use_req_params', 'Unique Names for Resources'], + ['test_unique_name_str_replace_use_req_params_in_tmpl', 'Unique Names for Resources'], + ['test_unique_resources_across_all_yaml_files', 'Resources'], + ['test_unique_resources_across_yaml_file', 'Unique Names for Resources'], + ['test_unique_resources_across_yaml_file', 'Resources'], + ['test_valid_nesting', 'Filenames'], + ['test_vm_type_assignments_on_nova_servers_only_use_get_param', 'Name, Flavor, and Image Assignments'], + ['test_vm_type_consistent_on_nova_servers', 'Name, Flavor, and Image Assignments'], + ['test_volume_format_outputs', 'Volumes'], + ['test_volume_outputs_consumed', 'Volumes'], + ['test_volume_resource_ids', 'Resources'], + ['test_volume_resource_ids', 'Volumes'], + ['test_volume_templates_contains_outputs', 'Volumes'], + ['test_volume_templates_only_contains_cinder', 'Volumes'], + ['test_volume_templates_outputs_match_resources', 'Volumes'], +] + +deployment_targets = [ + ['AIC', '2.5'], + ['AIC', '3.0'], + ['AIC', '3.5'], + ['AIC', '4.0'], + ['Other', 'No version number available'] +] + +ecomps = [ + ['Unknown'] +] + +deployment_targets_sites = [ + "Alpharetta (PDK2)", + "Willows (RDM2)", + "Willows (RDM3)", + "Middletown (ICENJ)", + "Lisle (DPA2)", + "Lisle (DPA3)", + "Palo Alto (PAO21)" +] + + +def execute_bootstrap_actions(): + create_roles() + create_companies() + create_deployment_targets() + create_ecomp() + create_deployment_targets_sites() + + # Non-default data: + create_standard_users() + create_el_users() + create_admin_users() + create_admin_ro_users() + create_templates() + create_validation_tests() + + +# TODO maybe enter this into migration scripts +def patch_migration_missing_fields(): + logger.info('Patching migration default fields') + vf_ids = VF.objects.filter() + if (vf_ids): + vf_list = ThinVFModelSerializer(vf_ids, many=True).data + for vf_data in vf_list: + # TODO remove into migration script + if vf_data['ecomp_release'] is None: + default_ecomp = ECOMPRelease.objects.get(name="Unknown") + vfObj = VF.objects.get(uuid=vf_data['uuid']) + vfObj.ecomp_release = default_ecomp + vfObj.save() + if vf_data['engagement']['reviewer'] is None: + # @UndefinedVariable + elRole = Role.objects.get(name=Roles.el.name) + ids_list = [] + for user in vf_data['engagement']['engagement_team']: + ids_list.append(user['uuid']) + # Fetch another random el Reviewer + qs = IceUserProfile.objects.all().filter(role=elRole).filter( + uuid__in=ids_list) # @UndefinedVariable + if qs.count() > 0: + elUser = IceUserProfile.objects.get(uuid=qs[0].uuid) + engagementObj = Engagement.objects.get( + uuid=vf_data['engagement']['uuid']) + engagementObj.reviewer = elUser + engagementObj.save() + + # TODO remove into migration script + if vf_data['engagement']['peer_reviewer'] is None: + # @UndefinedVariable + elRole = Role.objects.get(name=Roles.el.name) + ids_list = [] + for user in vf_data['engagement']['engagement_team']: + ids_list.append(user['uuid']) + # Fetch another random el to be a Peer Reviewer + qs = IceUserProfile.objects.all().filter(role=elRole).exclude( + uuid__in=ids_list) # @UndefinedVariable + if qs.count() > 0: + randUser = qs[random.randint(0, qs.count() - 1)] + prUser = IceUserProfile.objects.get(uuid=randUser.uuid) + engagementObj = Engagement.objects.get( + uuid=vf_data['engagement']['uuid']) + engagementObj.peer_reviewer = prUser + engagementObj.save() + + +# TODO remove after check engine is connected +def populate_checklist_automation_value(): + logger.info('Populating existing checklist with decisions value') + + outerframes = inspect.getouterframes(inspect.currentframe()) + for outerframe in outerframes: + if ('unittest' in str(outerframe)): + logger.error( + "Avoiding setting checklists in automation to be review since this is a test run: " + logEncoding(outerframe)) + return + + checklists = Checklist.objects.filter(state='automation') + first = True + for checklist in checklists: + checklist = Checklist.objects.get(uuid=checklist.uuid) + if (first): + checklist.state = 'review' + else: + checklist.state = 'peer_review' + checklist.save() + # first = False + decisions = ChecklistDecision.objects.filter(checklist=checklist) + first_decision = True + for decision in decisions: + decision = ChecklistDecision.objects.get(uuid=decision.uuid) + line_item = ChecklistLineItem.objects.get(uuid=decision.line_item_id) + if line_item.line_type == 'auto': + rand_decision_value = bool(random.getrandbits(1)) + if rand_decision_value: + decision.review_value = 'approved' + else: + decision.review_value = 'denied' + decision.save() + + +def create_templates(): + logger.info('Creating Checklist templates') + for template in checklist_templates: + created_template, created = ChecklistTemplate.objects.get_or_create(name=template['name'], + defaults={ + 'category': template['category'], + 'version': template['version'], + 'create_time': timezone.now() + }) + for section in template['sections']: + created_section = ChecklistSection.objects.get_or_create(name=section['name'], + template_id=created_template.uuid, + defaults={ + 'weight': section['weight'], + 'description': section['description'], + 'validation_instructions': section['validation_instructions'] + + }) + created_section = ChecklistSection.objects.get( + name=section['name'], template_id=created_template.uuid) + for line_item in section['line_items']: + created_line_item = ChecklistLineItem.objects.get_or_create(name=line_item['name'], + section_id=created_section.uuid, + template_id=created_template.uuid, + defaults={ + 'weight': line_item['weight'], + 'description': line_item['description'], + 'validation_instructions': line_item['validation_instructions'], + 'line_type': line_item['line_type'], + 'section_id': created_section.uuid, + }) + + +def create_validation_tests(): + logger.info('Creating Validation Tests') + template = ChecklistTemplate.objects.get(category='heat') + for test_name, line_item_name in validation_tests: + line_item = ChecklistLineItem.objects.get(name=line_item_name, template=template) + if line_item: + validation_test, status = ValidationTest.objects.get_or_create(name=test_name) + validation_test.line_items.add(line_item) + + +def create_roles(): + role_standard_user, created = Role.objects.get_or_create( + name=Roles.standard_user.name) # @UndefinedVariable + Constants.role_standard_user = role_standard_user + logger.info( + 'user role found or created : ' + logEncoding(role_standard_user)) + + role_el, created = Role.objects.get_or_create( + name=Roles.el.name) # @UndefinedVariable + Constants.role_el = role_el + logger.info('user role found or created : ' + logEncoding(role_el)) + + role_admin, created = Role.objects.get_or_create( + name=Roles.admin.name) # @UndefinedVariable + Constants.role_admin = role_admin + logger.info('user role found or created : ' + logEncoding(role_admin)) + + role_admin_ro, created = Role.objects.get_or_create( + name=Roles.admin_ro.name) # @UndefinedVariable + Constants.role_admin_ro = role_admin_ro + logger.info('user role found or created : ' + logEncoding(role_admin_ro)) + + +def create_companies(): + service_provider_company = None + created = None + try: + service_provider_company, created = Vendor.objects.get_or_create( + name=Constants.service_provider_company_name, public=True) + Constants.service_provider_company = service_provider_company + logger.info('The company was found or created : ' + str(service_provider_company)) + except Exception as e: + logger.error("bootstrap_actions - create_companies error:") + logger.error(e) + logger.error('The company could not be found or created : ' + Constants.service_provider_company_name) + + for company in companies_not_public: + try: + company, created = Vendor.objects.get_or_create( + name=company, public=False) # @UndefinedVariable + logger.info('The company was found or created : ' + str(company)) + except Exception as e: + logger.error("bootstrap_actions - create_companies error:") + logger.error(e) + logger.error( + 'The company could not be found or created.' + str(company)) + + for company in companies: + try: + company, created = Vendor.objects.get_or_create( + name=company, public=True) # @UndefinedVariable + logger.info('The company was found or created : ' + str(company)) + except Exception as e: + logger.error("bootstrap_actions - create_companies error:") + logger.error(e) + logger.error( + 'The company could not be found or created.' + str(company)) + + try: + company_other, created = Vendor.objects.get_or_create( + name='Other', public=True, defaults={'public': True}) + logger.info('The company was found or created : ' + str(company_other)) + except Exception as e: + logger.error("bootstrap_actions - create_deployment_targets error:") + logger.error(e) + logger.error('The company could not be found or created : Other') + + +"""expected: nothing , result: IceUserProfiles with el role creation""" + + +def create_standard_users(): + service_provider_company = Vendor.objects.get(name=Constants.service_provider_company_name) + user_role = Role.objects.get(name="standard_user") + user_list = dummy_users + + for user in user_list: + try: + user_object, created = CustomUser.objects.get_or_create(username=user[1], defaults={ + 'is_active': True, 'email': user[1], 'activation_token': uuid4(), 'activation_token_create_time': timezone.now()}) + user_object.set_password('iceusers') + user_object.save() + data = createUserTemplate( + service_provider_company, user[0], user_role, user[2], True, None, True, user_object) + standard_user, profile_created = IceUserProfile.objects.update_or_create( + email=user_object.email, defaults=data) + logger.info( + 'The Standard user was found or created: ' + str(standard_user.full_name)) + except Exception as e: + logger.error("bootstrap_actions - create_el_users error:") + logger.error(e) + logger.error('The EL User could not be found or created.') + + +def create_el_users(): + service_provider_company = Vendor.objects.get(name=Constants.service_provider_company_name) + el_role = Role.objects.get(name="el") + el_list = el_dummy_users + + for user in el_list: + try: + user_object, created = CustomUser.objects.get_or_create(username=user[1], defaults={ + 'is_active': True, 'email': user[1], 'activation_token': uuid4(), 'activation_token_create_time': timezone.now()}) + user_object.set_password('iceusers') + user_object.save() + data = createUserTemplate( + service_provider_company, user[0], el_role, user[2], True, None, True, user_object) + el_user, profile_created = IceUserProfile.objects.update_or_create( + email=user_object.email, defaults=data) + logger.info( + 'The EL user was found or created: ' + str(el_user.full_name)) + except Exception as e: + logger.error("bootstrap_actions - create_el_users error:") + logger.error(e) + logger.error('The EL User could not be found or created.') + + +def create_admin_users(): + service_provider_company = Vendor.objects.get(name=Constants.service_provider_company_name) + admin_role = Role.objects.get(name=Roles.admin.name) # @UndefinedVariable + + admin_list = admin_dummy_users + + for user in admin_list: + try: + user_object, created = CustomUser.objects.get_or_create(username=user[1], defaults={'is_active': True, 'email': user[ + 1], 'password': "iceusers", 'activation_token': uuid4(), 'activation_token_create_time': timezone.now()}) + user_object.set_password('iceusers') + user_object.save() + data = createUserTemplate( + service_provider_company, user[0], admin_role, user[2], True, None, True, user_object) + admin_user, profile_created = IceUserProfile.objects.update_or_create( + email=user_object.email, defaults=data) + logger.info( + 'The admin user was found or created: ' + str(admin_user.full_name)) + except Exception as e: + logger.error("bootstrap_actions - create_admin_users error:") + logger.error(e) + logger.error('The admin user could not be found or created.') + + +def create_admin_ro_users(): + service_provider_company = Vendor.objects.get(name=Constants.service_provider_company_name) + admin_ro_role = Role.objects.get( + name=Roles.admin_ro.name) # @UndefinedVariable + + admin_ro_list = admin_ro_dummy_users + + for user in admin_ro_list: + try: + user_object, created = CustomUser.objects.get_or_create(username=user[1], defaults={'is_active': True, 'email': user[ + 1], 'password': "iceusers", 'activation_token': uuid4(), 'activation_token_create_time': timezone.now()}) + user_object.set_password('iceusers') + user_object.save() + data = createUserTemplate( + service_provider_company, user[0], admin_ro_role, user[2], True, None, True, user_object) + admin_ro_user, profile_created = IceUserProfile.objects.update_or_create( + email=user_object.email, defaults=data) + logger.info( + 'The admin_ro user was found or created: ' + str(admin_ro_user.full_name)) + except Exception as e: + logger.error("bootstrap_actions - create_admin_ro_users error:") + logger.error(e) + logger.error('The admin_ro user could not be found or created.') + + +"""expected: nothing , result: Deployment Target objects creation""" + + +def create_deployment_targets(): + for dt in deployment_targets: + try: + deployment_target, created = DeploymentTarget.objects.get_or_create( + name=dt[0], version=dt[1], defaults={'version': dt[1]}) + logger.info( + 'Deployment Target found or created: ' + str(deployment_target)) + except Exception as e: + logger.error( + "bootstrap_actions - create_deployment_targets error:") + logger.error(e) + logger.error( + 'Deployment Target could not be found or created : ' + str(dt)) + + +"""expected: nothing , result: ECOMP objects creation""" + + +def create_ecomp(): + for dt in ecomps: + try: + ecomp, created = ECOMPRelease.objects.get_or_create( + name=dt[0]) + logger.info('ECOMP Release found or created: ' + str(ecomp)) + except Exception as e: + logger.error("bootstrap_actions - create_ecomp error:") + logger.error(e) + logger.error( + 'ECOMP Release could not be found or created : ' + str(dt)) + + +"""expected: nothing , result: creation of Deployment Target Sites objects""" + + +def create_deployment_targets_sites(): + for dt in deployment_targets_sites: + try: + deployment_target_site, created = DeploymentTargetSite.objects.get_or_create( + name=dt) + logger.info( + 'Deployment Target found or created: ' + str(deployment_target_site.name)) + except Exception as e: + logger.error( + "bootstrap_actions - create_deployment_targets_sites error:") + logger.error(e) + logger.error( + 'Deployment Target could not be found or created : ' + str(dt)) diff --git a/django/engagementmanager/management/commands/populate_all_gitlab_repo_and_user_and_jenkins.py b/django/engagementmanager/management/commands/populate_all_gitlab_repo_and_user_and_jenkins.py new file mode 100755 index 0000000..2d6c5be --- /dev/null +++ b/django/engagementmanager/management/commands/populate_all_gitlab_repo_and_user_and_jenkins.py @@ -0,0 +1,78 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +""" populate_all_gitlab_repo_and_user_and_jenkins +Will populate gitlab and jenkins with vf data (where it's not exists). + +This command will be used for systems with missing gitlab/jenkins data for some vfs. +""" +from django.core.management.base import BaseCommand +from rest_framework.status import HTTP_200_OK +from engagementmanager.models import VF +from engagementmanager.utils.constants import EngagementStage +from engagementmanager.utils.validator import logEncoding +from engagementmanager.vm_integration import vm_client +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class Command(BaseCommand): + + def handle(self, *args, **options): + engStageList = [EngagementStage.Intake.name, EngagementStage.Active.name, + EngagementStage.Validated.name, EngagementStage.Completed.name] + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList) + log_array = [] + error_array = [] + for vf_found in vf_list: + logger.debug(vf_found.uuid) + msg, http_status, values = vm_client.send_provision_new_vf_event(vf_found) + vf_dict = { + 'vf_uuid': vf_found.uuid, + 'msg': msg, + 'http_status': http_status, + 'values': values + } + + log_array.append(vf_dict) + if (http_status != HTTP_200_OK): + error_array.append(vf_dict) + + logger.error("==== populate jenkins _ gitlab error log ======") + logger.error(logEncoding(error_array)) diff --git a/django/engagementmanager/management/commands/render_rgwa_credentials.py b/django/engagementmanager/management/commands/render_rgwa_credentials.py new file mode 100755 index 0000000..52a1373 --- /dev/null +++ b/django/engagementmanager/management/commands/render_rgwa_credentials.py @@ -0,0 +1,61 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +""" render_rgwa_credentials +Will create rados gateway user (S3 API) for each django user. + +This command will create the user if it's not exists so it safe to run it even the user are exists. +This command is part of bucket usage (images) efforts. +""" +from django.db.models import Q +from engagementmanager.models import IceUserProfile +from validationmanager.em_integration.vm_api import create_user_rgwa +from django.core.management.base import BaseCommand +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class Command(BaseCommand): + + def handle(self, *args, **options): + logger.debug("About to generate RGWA credentials for existing users") + users = IceUserProfile.objects.filter( + Q(rgwa_secret_key=None) | Q(rgwa_access_key=None)) + for user in users: + create_user_rgwa(user) diff --git a/django/engagementmanager/migrations/0001_initial.py b/django/engagementmanager/migrations/0001_initial.py new file mode 100755 index 0000000..ffbb95a --- /dev/null +++ b/django/engagementmanager/migrations/0001_initial.py @@ -0,0 +1,396 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-06-13 14:07 +from __future__ import unicode_literals + +import datetime + +from django.db import migrations, models +import django.db.models.deletion +from django.utils.timezone import utc +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Activity', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False, unique=True)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now)), + ('description', models.CharField(max_length=512)), + ('is_notification', models.BooleanField(default=False)), + ('activity_type', models.CharField(choices=[ + (b'3', b'eng_validation_request'), (b'4', b'next_steps'), (b'2', b'ssh_key_added'), (b'1', b'user_joined_eng')], max_length=36)), + ('metadata', models.CharField(max_length=1024)), + ], + options={ + 'ordering': ['-create_time'], + 'db_table': 'ice_activity', + }, + ), + migrations.CreateModel( + name='ApplicationServiceInfrastructure', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('uuid', models.CharField(max_length=36, unique=True)), + ], + options={ + 'db_table': 'ice_application_service_infrastructure', + }, + ), + migrations.CreateModel( + name='ContactRequest', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('uuid', models.CharField(max_length=36, unique=True)), + ('fname', models.CharField(max_length=50)), + ('lname', models.CharField(max_length=50)), + ('email', models.EmailField(max_length=254, verbose_name='email')), + ('company', models.CharField(max_length=50)), + ('phone_number', models.CharField(max_length=30)), + ('message', models.TextField()), + ], + options={ + 'db_table': 'ice_contact_request', + }, + ), + migrations.CreateModel( + name='DeploymentTarget', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=45)), + ('version', models.CharField(max_length=100)), + ], + options={ + 'db_table': 'ice_deployment_target', + }, + ), + migrations.CreateModel( + name='Engagement', + fields=[ + ('uuid', models.CharField(max_length=64, primary_key=True, serialize=False)), + ('engagement_manual_id', models.CharField(blank=True, max_length=36, null=True)), + ('progress', models.IntegerField(default=0)), + ('target_completion_date', models.DateField(blank=True, default=datetime.datetime( + 2016, 6, 29, 14, 7, 41, 103000, tzinfo=utc), null=True)), + ('engagement_stage', models.CharField(default=b'Intake', max_length=15)), + ], + options={ + 'db_table': 'ice_engagement', + }, + ), + migrations.CreateModel( + name='EngagementRequest', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('uuid', models.CharField(max_length=36, unique=True)), + ('fname', models.CharField(max_length=50)), + ('lname', models.CharField(max_length=50)), + ('email', models.EmailField(max_length=254, verbose_name='email')), + ('company', models.CharField(max_length=50)), + ('country_code', models.CharField(max_length=5)), + ('phone_number', models.CharField(max_length=30)), + ('vf_csv', models.CharField(max_length=80)), + ('att_contact_fname', models.CharField(max_length=50)), + ('att_contact_lname', models.CharField(max_length=50)), + ('att_contact_email', models.EmailField(max_length=254, verbose_name='email')), + ('att_contact_phone', models.CharField(max_length=30)), + ('request_type', models.CharField(max_length=20)), + ('description', models.TextField()), + ('mail_subscription', models.BooleanField()), + ], + options={ + 'db_table': 'ice_engagement_request', + }, + ), + migrations.CreateModel( + name='IceUser', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(max_length=36, unique=True)), + ('phone_number', models.CharField(max_length=30)), + ('full_name', models.CharField(max_length=30)), + ('email', models.EmailField(max_length=254, unique=True, verbose_name='email')), + ('password', models.CharField(max_length=256)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last_login')), + ('ssh_public_key', models.CharField( + blank=True, max_length=1024, null=True, verbose_name='ssh_public_key')), + ('regular_email_updates', models.BooleanField(default=False)), + ('email_updates_on_every_notification', models.BooleanField(default=True)), + ('email_updates_daily_digest', models.BooleanField(default=False)), + ('is_active', models.BooleanField()), + ('is_att_contact', models.BooleanField()), + ('activation_token', models.CharField(max_length=128, unique=True)), + ('activation_token_create_time', models.DateTimeField( + default=django.utils.timezone.now, verbose_name='activation_token_create_time')), + ], + options={ + 'db_table': 'ice_user', + }, + ), + migrations.CreateModel( + name='NextStep', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('last_update_time', models.DateTimeField( + default=django.utils.timezone.now, verbose_name='last update time')), + ('last_update_type', models.CharField(default='Added', max_length=15)), + ('position', models.IntegerField()), + ('description', models.TextField()), + ('state', models.CharField(max_length=15)), + ('engagement_stage', models.CharField(max_length=15)), + ('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, + related_name='NextStep_creator', to='engagementmanager.IceUser')), + ('engagement', models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Engagement')), + ('last_updater', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='NextStep_last_updater', to='engagementmanager.IceUser')), + ], + options={ + 'db_table': 'ice_next_step', + 'verbose_name_plural': 'Next steps', + }, + ), + migrations.CreateModel( + name='Notification', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False, unique=True)), + ('is_sent', models.BooleanField(default=False)), + ('is_read', models.BooleanField(default=False)), + ('activity', models.ForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Activity')), + ('user', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUser')), + ], + options={ + 'db_table': 'ice_notification', + }, + ), + migrations.CreateModel( + name='Role', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(max_length=36, unique=True)), + ('name', models.CharField(max_length=36, unique=True)), + ], + options={ + 'db_table': 'ice_role', + }, + ), + migrations.CreateModel( + name='Test', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=45)), + ('uuid', models.CharField(max_length=36, unique=True)), + ], + options={ + 'db_table': 'ice_test', + }, + ), + migrations.CreateModel( + name='ValidationCycle', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(max_length=36, unique=True)), + ('start_date', models.DateTimeField()), + ('end_date', models.DateTimeField()), + ('validated_by', models.CharField(max_length=45)), + ('validated_at', models.DateTimeField()), + ('peer_reviewer', models.CharField(max_length=45)), + ('peer_reviewed_at', models.DateTimeField()), + ('package_uuid', models.CharField(max_length=45)), + ('package_cksum', models.CharField(max_length=45)), + ('package_approval_date', models.DateTimeField()), + ('package_approver', models.CharField(max_length=45)), + ('image_uuid', models.CharField(max_length=45)), + ('image_name', models.CharField(max_length=100)), + ('image_cksum', models.CharField(max_length=100)), + ('passed', models.BooleanField()), + ], + options={ + 'db_table': 'ice_validation_cycle', + }, + ), + migrations.CreateModel( + name='ValidationException', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(max_length=36, unique=True)), + ('type', models.CharField(max_length=45)), + ('external_ref_id', models.CharField(max_length=45)), + ], + options={ + 'db_table': 'ice_validation_exception', + }, + ), + migrations.CreateModel( + name='ValidationSteps', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(max_length=36)), + ('requirment_id', models.CharField(blank=True, max_length=36, null=True)), + ('passed', models.BooleanField()), + ('log', models.BinaryField()), + ('validation_notes', models.CharField(blank=True, max_length=200, null=True)), + ('test', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Test')), + ('validation_cycle', models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.ValidationCycle')), + ('validation_exceptions', models.ManyToManyField(to='engagementmanager.ValidationException')), + ], + options={ + 'db_table': 'ice_validation_step', + 'verbose_name_plural': 'Validation steps', + }, + ), + migrations.CreateModel( + name='Vendor', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(max_length=36, unique=True)), + ('name', models.CharField(max_length=100, unique=True)), + ], + options={ + 'db_table': 'ice_vendor', + }, + ), + migrations.CreateModel( + name='VF', + fields=[ + ('name', models.CharField(max_length=100)), + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False, unique=True)), + ('is_att_internal', models.BooleanField(default=False)), + ('git_repo_url', models.CharField(blank=True, max_length=512, null=True)), + ('target_lab_entry_date', models.DateField(verbose_name='target_lab_entry_date')), + ('deployment_target', models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.SET_NULL, to='engagementmanager.DeploymentTarget')), + ('engagement', models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.SET_NULL, to='engagementmanager.Engagement')), + ('vendor', models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Vendor')), + ], + options={ + 'db_table': 'ice_vf', + }, + ), + migrations.CreateModel( + name='VFC', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=45)), + ('version', models.CharField(max_length=45)), + ('uuid', models.CharField(max_length=36, unique=True)), + ('vf_acronym', models.CharField(blank=True, max_length=100, null=True)), + ('vf', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.VF')), + ], + options={ + 'db_table': 'ice_vfc', + }, + ), + migrations.AlterUniqueTogether( + name='validationexception', + unique_together=set([('uuid', 'type')]), + ), + migrations.AddField( + model_name='validationcycle', + name='vfc', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.VFC'), + ), + migrations.AddField( + model_name='iceuser', + name='company', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Vendor'), + ), + migrations.AddField( + model_name='iceuser', + name='role', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Role'), + ), + migrations.AddField( + model_name='engagement', + name='contact_user', + field=models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.IceUser'), + ), + migrations.AddField( + model_name='engagement', + name='engagement_team', + field=models.ManyToManyField(related_name='members', to='engagementmanager.IceUser'), + ), + migrations.AlterUniqueTogether( + name='deploymenttarget', + unique_together=set([('name', 'version')]), + ), + migrations.AlterUniqueTogether( + name='applicationserviceinfrastructure', + unique_together=set([('name', 'uuid')]), + ), + migrations.AddField( + model_name='activity', + name='activity_owner', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.IceUser'), + ), + migrations.AddField( + model_name='activity', + name='engagement', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Engagement'), + ), + migrations.AlterUniqueTogether( + name='vfc', + unique_together=set([('name', 'version')]), + ), + migrations.AlterUniqueTogether( + name='validationsteps', + unique_together=set([('uuid', 'requirment_id')]), + ), + ] diff --git a/django/engagementmanager/migrations/0001_squashed_initial.py b/django/engagementmanager/migrations/0001_squashed_initial.py new file mode 100755 index 0000000..1be6a07 --- /dev/null +++ b/django/engagementmanager/migrations/0001_squashed_initial.py @@ -0,0 +1,639 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from __future__ import unicode_literals +from django.conf import settings +import django.contrib.auth.models +from django.db import models +import django.db.models.deletion +from django.utils.timezone import utc +import django.utils.timezone +import engagementmanager.models +import uuid +import os +from django.db import migrations, connection +import engagementmanager +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def forwards(apps, schema_editor): + if not schema_editor.connection.alias == 'default': + return + + cursor = connection.cursor() + cursor.execute(open(os.path.join(os.path.dirname(engagementmanager.__file__), + 'sql-scripts/generate_excel_overview_sheet_procedure.sql'), "r").read()) + + +def create_user_for_pre_user_profiles(apps, schema_editor): + CustomUser = apps.get_model("engagementmanager", "CustomUser") + IceUserProfile = apps.get_model("engagementmanager", "IceUserProfile") + users_list = IceUserProfile.objects.filter(user=None) + count = 0 + for profile in users_list: + try: + custom_user, created = CustomUser.objects.get_or_create(username=profile.email) + custom_user.is_active = profile.is_active + custom_user.email = profile.email + custom_user.activation_token = profile.activation_token + custom_user.password = profile.password + custom_user.activation_token_create_time = profile.activation_token_create_time + custom_user.save() + profile.user = custom_user + profile.save() + + except Exception as e: + logger.error("migrations fail, error:") + logger.error(e.message) + + +class Migration(migrations.Migration): + replaces = [('engagementmanager', '0001_initial'), ('engagementmanager', '0002_auto_20160704_1028'), + ('engagementmanager', '0003_auto_20160713_0929'), ('engagementmanager', '0004_auto_20160720_2143'), + ('engagementmanager', '0005_auto_20160815_1248'), ('engagementmanager', '0006_auto_20160825_0644'), + ('engagementmanager', '0007_auto_20160922_0421'), ('engagementmanager', '0008_auto_20161009_1210'), + ('engagementmanager', '0009_auto_20161018_0740'), ('engagementmanager', '0010_auto_20161025_0838'), + ('engagementmanager', '0011_auto_20161109_0811'), ('engagementmanager', '0012_auto_20161109_0822'), + ('engagementmanager', '0013_auto_20161128_1159'), ('engagementmanager', '0014_auto_20161129_1145'), + ('engagementmanager', '0015_engagementstatus'), ('engagementmanager', '0016_auto_20161208_0842'), + ('engagementmanager', '0017_auto_20161215_1535'), ('engagementmanager', '0018_set_old_notif_true'), + ('engagementmanager', '0019_auto_20170104_1715'), ('engagementmanager', '0020_add_indexes_20170108'), + ('engagementmanager', '0021_generate_excel_overview_sheet_procedure_20170110'), + ('engagementmanager', '0022_auto_20170118_1520'), ('engagementmanager', '0023_auto_20170123_1445'), + ('engagementmanager', '0024_auto_20170227_1224'), + ('engagementmanager', '0025_change_nextsteps_to_new_state'), + ('engagementmanager', '0026_add_slack_handle_to_ice_user_profile'), + ('engagementmanager', '0027_add_version_to_vf'), ('engagementmanager', '0028_auto_20170425_1310'), + ('engagementmanager', '0029_auto_20170504_0749'), + ('engagementmanager', '0030_engagement_archived_time'), + ('engagementmanager', '0031_auto_20170620_1312'), ('engagementmanager', '0032_auto_20170702_1435'), + ('engagementmanager', '0033_auto_20170704_0635'), + ('engagementmanager', '0034_engagement_is_with_files'), ('engagementmanager', '0035_rgwa_fields'), + ('engagementmanager', '0036_auto_20170906_0935')] + + initial = True + + dependencies = [ + ('auth', '0008_alter_user_username_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='Activity', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now)), + ('description', models.CharField(max_length=512)), + ('is_notification', models.BooleanField(default=False)), + ('activity_type', models.CharField(choices=[('user_joined_eng', 'user_joined_eng'), ('ssh_key_added', 'ssh_key_added'), ('eng_validation_request', 'eng_validation_request'), ('update_next_steps', 'update_next_steps'), ('vfc', 'vfc'), ('change_checklist_state', 'change_checklist_state'), ('vf_provisioning_event', 'vf_provisioning_event'), ('test_finished_event', 'test_finished_event'), ('change_engagement_stage', 'change_engagement_stage'), ('add_next_steps', 'add_next_steps'), ('delete_next_steps', 'delete_next_steps'), ('notice_empty_engagement', 'notice_empty_engagement')], max_length=36)), + ('metadata', models.CharField(max_length=1024)), + ], + options={ + 'db_table': 'ice_activity', + 'ordering': ['-create_time'], + }, + ), + migrations.CreateModel( + name='ApplicationServiceInfrastructure', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, unique=True)), + ], + options={ + 'db_table': 'ice_application_service_infrastructure', + }, + ), + migrations.CreateModel( + name='Checklist', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='checklist name')), + ('state', models.CharField(choices=[('automation', 'automation'), ('review', 'review'), ('peer_review', 'peer_review'), ('approval', 'approval'), ('handoff', 'handoff'), ('closed', 'closed'), ('archive', 'archive'), ('pending', 'pending')], default='pending', max_length=36)), + ('validation_cycle', models.IntegerField(verbose_name='validation cycle')), + ('weight', models.FloatField(default=0, verbose_name='checklist weight')), + ('associated_files', models.TextField(verbose_name='list of files from gitlab')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ], + options={ + 'db_table': 'ice_checklist', + }, + ), + migrations.CreateModel( + name='ChecklistAuditLog', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('category', models.CharField(max_length=255)), + ('description', models.TextField()), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ('checklist', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Checklist')), + ], + options={ + 'db_table': 'ice_checklist_audit_log', + }, + ), + migrations.CreateModel( + name='ChecklistDecision', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('review_value', models.CharField(choices=[('approved', 'approved'), ('denied', 'denied'), ('not_relevant', 'not_relevant'), ('na', 'na')], max_length=36)), + ('peer_review_value', models.CharField(choices=[('approved', 'approved'), ('denied', 'denied'), ('not_relevant', 'not_relevant'), ('na', 'na')], max_length=36)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ('checklist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Checklist')), + ], + options={ + 'db_table': 'ice_checklist_decision', + }, + ), + migrations.CreateModel( + name='ChecklistLineItem', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='line name')), + ('weight', models.FloatField(verbose_name='line weight')), + ('description', models.TextField(verbose_name='line description')), + ('line_type', models.CharField(choices=[('auto', 'auto'), ('manual', 'manual')], default='auto', max_length=36)), + ('validation_instructions', models.TextField(verbose_name='line validation instructions')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ], + options={ + 'db_table': 'ice_checklist_line_item', + }, + ), + migrations.CreateModel( + name='ChecklistSection', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='section name')), + ('weight', models.FloatField(verbose_name='checklist weight')), + ('description', models.TextField(verbose_name='section description')), + ('validation_instructions', models.TextField(verbose_name='section validation instructions')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ('parent_section', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.ChecklistSection')), + ], + options={ + 'db_table': 'ice_checklist_section', + }, + ), + migrations.CreateModel( + name='ChecklistTemplate', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='template name')), + ('category', models.CharField(choices=[('overall', 'overall'), ('heat', 'heat'), ('glance', 'glance'), ('instantiation', 'instantiation'), ('asdc', 'asdc')], default='overall', max_length=36)), + ('version', models.IntegerField(verbose_name='template version')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ], + options={ + 'db_table': 'ice_checklist_template', + }, + ), + migrations.CreateModel( + name='CustomUser', + fields=[ + ('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), + ('activation_token', models.CharField(max_length=128, null=True, unique=True)), + ('activation_token_create_time', models.DateTimeField(default=django.utils.timezone.now, null=True, verbose_name='activation_token_create_time')), + ('temp_password', models.CharField(blank=True, default=None, max_length=256, null=True)), + ], + options={ + 'db_table': 'ice_custom_user', + }, + bases=('auth.user',), + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='DeploymentTarget', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=45)), + ('version', models.CharField(max_length=100)), + ('weight', models.IntegerField(default=1)), + ('ui_visibility', models.BooleanField(default=True)), + ], + options={ + 'db_table': 'ice_deployment_target', + }, + ), + migrations.CreateModel( + name='DeploymentTargetSite', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=45)), + ], + options={ + 'db_table': 'ice_deployment_target_site', + }, + ), + migrations.CreateModel( + name='ECOMPRelease', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=45)), + ('weight', models.IntegerField(default=1)), + ('ui_visibility', models.BooleanField(default=True)), + ], + options={ + 'db_table': 'ice_ecomp_release', + }, + ), + migrations.CreateModel( + name='Engagement', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=64, primary_key=True, serialize=False)), + ('engagement_manual_id', models.CharField(db_index=True, default=-1, max_length=36)), + ('progress', models.IntegerField(default=0)), + ('target_completion_date', models.DateField(blank=True, default=engagementmanager.models.get_default_target_completion_date, null=True)), + ('engagement_stage', models.CharField(choices=[('Intake', 'Intake'), ('Active', 'Active'), ('Validated', 'Validated'), ('Completed', 'Completed'), ('Archived', 'Archived')], db_index=True, default='Intake', max_length=15)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('heat_validated_time', models.DateTimeField(blank=True, null=True, verbose_name='heat validated time')), + ('image_scan_time', models.DateTimeField(blank=True, null=True, verbose_name='image scan time')), + ('aic_instantiation_time', models.DateTimeField(blank=True, null=True, verbose_name='aic instantiation time')), + ('asdc_onboarding_time', models.DateTimeField(blank=True, null=True, verbose_name='asdc onboarding time')), + ('started_state_time', models.DateTimeField(blank=True, null=True, verbose_name='started state time')), + ('intake_time', models.DateTimeField(blank=True, null=True, verbose_name='intake time')), + ('active_time', models.DateTimeField(blank=True, null=True, verbose_name='active time')), + ('validated_time', models.DateTimeField(blank=True, null=True, verbose_name='validated time')), + ('completed_time', models.DateTimeField(blank=True, null=True, verbose_name='completed time')), + ('archive_reason', models.TextField(default=None, null=True)), + ('archived_time', models.DateTimeField(blank=True, null=True, verbose_name='archived time')), + ('is_with_files', models.BooleanField(default=False)), + ], + options={ + 'db_table': 'ice_engagement', + }, + ), + migrations.CreateModel( + name='EngagementStatus', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=64, primary_key=True, serialize=False)), + ('description', models.CharField(max_length=256)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now)), + ('update_time', models.DateTimeField(default=django.utils.timezone.now)), + ], + options={ + 'db_table': 'ice_engagement_status', + }, + ), + migrations.CreateModel( + name='Feedback', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now)), + ('description', models.TextField(verbose_name='feedback_description')), + ], + options={ + 'db_table': 'ice_feedback', + }, + ), + migrations.CreateModel( + name='IceUserProfile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, unique=True)), + ('phone_number', models.CharField(max_length=30)), + ('full_name', models.CharField(max_length=30)), + ('email', models.EmailField(db_index=True, max_length=254, unique=True, verbose_name='email')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('ssh_public_key', models.CharField(blank=True, max_length=1024, null=True, verbose_name='ssh_public_key')), + ('regular_email_updates', models.BooleanField(default=False)), + ('email_updates_on_every_notification', models.BooleanField(default=True)), + ('email_updates_daily_digest', models.BooleanField(default=False)), + ('is_service_provider_contact', models.BooleanField(default=False)), + ('rgwa_access_key', models.CharField(blank=True, max_length=1024, null=True, unique=True)), + ('rgwa_secret_key', models.CharField(blank=True, max_length=1024, null=True, unique=True)), + ('slack_handle', models.CharField(blank=True, default=None, max_length=64, null=True)), + ], + options={ + 'db_table': 'ice_user_profile', + }, + ), + migrations.CreateModel( + name='Invitation', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('engagement_uuid', models.CharField(db_index=True, max_length=64)), + ('invited_by_user_uuid', models.CharField(db_index=True, max_length=64)), + ('email', models.CharField(max_length=255)), + ('invitation_token', models.CharField(db_index=True, max_length=1024)), + ('accepted', models.BooleanField(default=False)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='invitation creation time')), + ], + options={ + 'db_table': 'ice_invitation', + }, + ), + migrations.CreateModel( + name='NextStep', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('last_update_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='last update time')), + ('last_update_type', models.CharField(default='Added', max_length=15)), + ('position', models.IntegerField()), + ('description', models.TextField()), + ('state', models.CharField(choices=[('Incomplete', 'Incomplete'), ('Completed', 'Completed')], max_length=15)), + ('engagement_stage', models.CharField(max_length=15)), + ('next_step_type', models.CharField(choices=[('set_ssh', 'set_ssh'), ('trial_agreements', 'trial_agreements'), ('add_contact_person', 'add_contact_person'), ('submit_vf_package', 'submit_vf_package'), ('el_handoff', 'el_handoff'), ('user_defined', 'user_defined')], default='user_defined', max_length=36)), + ('files', models.TextField(null=True, verbose_name='list of files')), + ('due_date', models.DateField(null=True, verbose_name='due_date')), + ('assignees', models.ManyToManyField(related_name='assignees', to='engagementmanager.IceUserProfile')), + ('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='NextStep_creator', to='engagementmanager.IceUserProfile')), + ('engagement', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Engagement')), + ('last_updater', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='NextStep_last_updater', to='engagementmanager.IceUserProfile')), + ('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.IceUserProfile')), + ], + options={ + 'verbose_name_plural': 'Next steps', + 'db_table': 'ice_next_step', + }, + ), + migrations.CreateModel( + name='Notification', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True)), + ('is_sent', models.BooleanField(default=False)), + ('is_read', models.BooleanField(default=False)), + ('activity', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Activity')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUserProfile')), + ], + options={ + 'db_table': 'ice_notification', + }, + ), + migrations.CreateModel( + name='RecentEngagement', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=64, primary_key=True, serialize=False)), + ('user_uuid', models.CharField(max_length=64)), + ('action_type', models.CharField(choices=[('JOINED_TO_ENGAGEMENT', 'JOINED_TO_ENGAGEMENT'), ('NEXT_STEP_ASSIGNED', 'NEXT_STEP_ASSIGNED'), ('GOT_OWNERSHIP_OVER_ENGAGEMENT', 'GOT_OWNERSHIP_OVER_ENGAGEMENT'), ('NAVIGATED_INTO_ENGAGEMENT', 'NAVIGATED_INTO_ENGAGEMENT'), ('NEW_VF_CREATED', 'NEW_VF_CREATED')], max_length=36)), + ('last_update', models.DateTimeField(default=django.utils.timezone.now, verbose_name='update time')), + ], + options={ + 'db_table': 'ice_recent_engagement', + }, + ), + migrations.CreateModel( + name='Role', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, unique=True)), + ('name', models.CharField(max_length=36, unique=True)), + ], + options={ + 'db_table': 'ice_role', + }, + ), + migrations.CreateModel( + name='Vendor', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, unique=True)), + ('name', models.CharField(max_length=100, unique=True)), + ('public', models.BooleanField()), + ], + options={ + 'db_table': 'ice_vendor', + }, + ), + migrations.CreateModel( + name='VF', + fields=[ + ('name', models.CharField(db_index=True, max_length=100)), + ('version', models.CharField(db_index=True, max_length=100, null=True)), + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True)), + ('is_service_provider_internal', models.BooleanField(default=False)), + ('git_repo_url', models.CharField(default=-1, max_length=512)), + ('target_lab_entry_date', models.DateField(verbose_name='target_lab_entry_date')), + ('deployment_target', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='engagementmanager.DeploymentTarget')), + ('deployment_target_sites', models.ManyToManyField(blank=True, default=None, related_name='DeployTarget_sites', to='engagementmanager.DeploymentTargetSite')), + ('ecomp_release', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.ECOMPRelease')), + ('engagement', models.OneToOneField(default=-1, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Engagement')), + ('vendor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Vendor')), + ], + options={ + 'db_table': 'ice_vf', + }, + ), + migrations.CreateModel( + name='VFC', + fields=[ + ('uuid', models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True)), + ('name', models.CharField(db_index=True, max_length=100)), + ('external_ref_id', models.CharField(default='', max_length=20)), + ('ice_mandated', models.BooleanField(default=False)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('company', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='engagementmanager.Vendor')), + ('creator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='Vfc_creator', to='engagementmanager.IceUserProfile')), + ('vf', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.VF')), + ], + options={ + 'db_table': 'ice_vfc', + }, + ), + migrations.AddField( + model_name='recentengagement', + name='vf', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.VF'), + ), + migrations.AlterUniqueTogether( + name='invitation', + unique_together=set([('engagement_uuid', 'email')]), + ), + migrations.AddField( + model_name='iceuserprofile', + name='company', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Vendor'), + ), + migrations.AddField( + model_name='iceuserprofile', + name='role', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Role'), + ), + migrations.AddField( + model_name='iceuserprofile', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.CustomUser'), + ), + migrations.AddField( + model_name='feedback', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='engagementstatus', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='status_creator', to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='engagementstatus', + name='engagement', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Engagement'), + ), + migrations.AddField( + model_name='engagement', + name='contact_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='Engagement_contact_user', to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='engagement', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='Engagement_creator', to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='engagement', + name='engagement_team', + field=models.ManyToManyField(related_name='members', to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='engagement', + name='peer_reviewer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='Engagement_peer_reviewer', to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='engagement', + name='reviewer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='Engagement_el_reviewer', to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='engagement', + name='starred_engagement', + field=models.ManyToManyField(blank=True, default=None, to='engagementmanager.IceUserProfile'), + ), + migrations.AlterUniqueTogether( + name='deploymenttarget', + unique_together=set([('name', 'version')]), + ), + migrations.AddField( + model_name='checklistsection', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.ChecklistTemplate'), + ), + migrations.AddField( + model_name='checklistlineitem', + name='section', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.ChecklistSection'), + ), + migrations.AddField( + model_name='checklistlineitem', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.ChecklistTemplate'), + ), + migrations.AddField( + model_name='checklistdecision', + name='lineitem', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.ChecklistLineItem'), + ), + migrations.AddField( + model_name='checklistdecision', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.ChecklistTemplate'), + ), + migrations.AddField( + model_name='checklistauditlog', + name='creator', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='checklistauditlog', + name='decision', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.ChecklistDecision'), + ), + migrations.AddField( + model_name='checklist', + name='creator', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='checklist_creator', to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='checklist', + name='engagement', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Engagement'), + ), + migrations.AddField( + model_name='checklist', + name='owner', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='checklist_owner', to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='checklist', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.ChecklistTemplate'), + ), + migrations.AlterUniqueTogether( + name='applicationserviceinfrastructure', + unique_together=set([('name', 'uuid')]), + ), + migrations.AddField( + model_name='activity', + name='activity_owner', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUserProfile'), + ), + migrations.AddField( + model_name='activity', + name='engagement', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Engagement'), + ), + migrations.AlterIndexTogether( + name='notification', + index_together=set([('user', 'is_read')]), + ), + migrations.AlterIndexTogether( + name='nextstep', + index_together=set([('engagement_stage', 'owner')]), + ), + migrations.AlterIndexTogether( + name='feedback', + index_together=set([('user',)]), + ), + migrations.AlterIndexTogether( + name='activity', + index_together=set([('engagement', 'activity_owner')]), + ), + migrations.RunPython(forwards), + migrations.RunPython(create_user_for_pre_user_profiles), + ] diff --git a/django/engagementmanager/migrations/0002_auto_20160704_1028.py b/django/engagementmanager/migrations/0002_auto_20160704_1028.py new file mode 100755 index 0000000..682394a --- /dev/null +++ b/django/engagementmanager/migrations/0002_auto_20160704_1028.py @@ -0,0 +1,176 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-04 07:28 +from __future__ import unicode_literals + +import datetime + +from django.db import migrations, models +import django.db.models.deletion +from django.utils.timezone import utc +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='validationcycle', + name='vfc', + ), + migrations.DeleteModel( + name='ValidationException', + ), + migrations.AlterUniqueTogether( + name='validationsteps', + unique_together=set([]), + ), + migrations.RemoveField( + model_name='validationsteps', + name='test', + ), + migrations.RemoveField( + model_name='validationsteps', + name='validation_cycle', + ), + migrations.RemoveField( + model_name='validationsteps', + name='validation_exceptions', + ), + migrations.AlterModelOptions( + name='nextstep', + options={}, + ), + migrations.AddField( + model_name='engagement', + name='create_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time'), + ), + migrations.AddField( + model_name='engagement', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Engagement_creator', to='engagementmanager.IceUser'), + ), + migrations.AddField( + model_name='vfc', + name='create_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time'), + ), + migrations.AddField( + model_name='vfc', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Vfc_creator', to='engagementmanager.IceUser'), + ), + migrations.AddField( + model_name='vfc', + name='external_ref_id', + field=models.CharField(default='', max_length=20), + ), + migrations.AddField( + model_name='vfc', + name='ice_mandated', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='activity', + name='activity_owner', + field=models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUser'), + ), + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[(b'3', b'eng_validation_request'), (b'4', b'next_steps'), + (b'2', b'ssh_key_added'), (b'1', b'user_joined_eng'), (b'5', b'vfc')], max_length=36), + ), + migrations.AlterField( + model_name='engagement', + name='contact_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Engagement_contact_user', to='engagementmanager.IceUser'), + ), + migrations.AlterField( + model_name='engagement', + name='target_completion_date', + field=models.DateField(blank=True, default=datetime.datetime( + 2016, 7, 20, 7, 28, 25, 168000, tzinfo=utc), null=True), + ), + migrations.AlterField( + model_name='vfc', + name='name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='vfc', + name='uuid', + field=models.CharField(max_length=36, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterUniqueTogether( + name='vfc', + unique_together=set([]), + ), + migrations.DeleteModel( + name='Test', + ), + migrations.DeleteModel( + name='ValidationCycle', + ), + migrations.DeleteModel( + name='ValidationSteps', + ), + migrations.RemoveField( + model_name='vfc', + name='id', + ), + migrations.RemoveField( + model_name='vfc', + name='version', + ), + migrations.RemoveField( + model_name='vfc', + name='vf_acronym', + ), + ] diff --git a/django/engagementmanager/migrations/0003_auto_20160713_0929.py b/django/engagementmanager/migrations/0003_auto_20160713_0929.py new file mode 100755 index 0000000..3bc94a0 --- /dev/null +++ b/django/engagementmanager/migrations/0003_auto_20160713_0929.py @@ -0,0 +1,85 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-13 09:29 +from __future__ import unicode_literals + +import datetime + +from django.db import migrations, models +import django.db.models.deletion +from django.utils.timezone import utc + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0002_auto_20160704_1028'), + ] + + operations = [ + migrations.AlterModelOptions( + name='nextstep', + options={'verbose_name_plural': 'Next steps'}, + ), + migrations.AddField( + model_name='nextstep', + name='next_step_type', + field=models.CharField(choices=[(b'(3,)', b'add_contact_person'), (b'(5,)', b'el_handoff'), (b'(1,)', b'set_ssh'), ( + b'(4,)', b'submit_vf_package'), (b'(2,)', b'trial_agreements'), (b'6', b'user_defined')], default=b'user_defined', max_length=36), + ), + migrations.AddField( + model_name='nextstep', + name='owner', + field=models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.IceUser'), + ), + migrations.AlterField( + model_name='engagement', + name='target_completion_date', + field=models.DateField(blank=True, default=datetime.datetime( + 2016, 7, 29, 9, 29, 32, 642800, tzinfo=utc), null=True), + ), + migrations.AlterField( + model_name='nextstep', + name='engagement', + field=models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Engagement'), + ), + ] diff --git a/django/engagementmanager/migrations/0004_auto_20160720_2143.py b/django/engagementmanager/migrations/0004_auto_20160720_2143.py new file mode 100755 index 0000000..cfc04d3 --- /dev/null +++ b/django/engagementmanager/migrations/0004_auto_20160720_2143.py @@ -0,0 +1,68 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. + +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-20 18:43 +from __future__ import unicode_literals + +import datetime + +from django.db import migrations, models +from django.utils.timezone import utc + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0003_auto_20160713_0929'), + ] + + operations = [ + migrations.AddField( + model_name='iceuser', + name='temp_password', + field=models.CharField(blank=True, default=None, max_length=256, null=True, unique=True), + ), + migrations.AlterField( + model_name='engagement', + name='target_completion_date', + field=models.DateField(blank=True, default=datetime.datetime( + 2016, 8, 5, 18, 43, 43, 473000, tzinfo=utc), null=True), + ), + ] diff --git a/django/engagementmanager/migrations/0005_auto_20160815_1248.py b/django/engagementmanager/migrations/0005_auto_20160815_1248.py new file mode 100755 index 0000000..decbe51 --- /dev/null +++ b/django/engagementmanager/migrations/0005_auto_20160815_1248.py @@ -0,0 +1,95 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-15 09:48 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + +import engagementmanager.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0004_auto_20160720_2143'), + ] + + operations = [ + migrations.CreateModel( + name='DeploymentTargetSite', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=45)), + ], + options={ + 'db_table': 'ice_deployment_target_site', + }, + ), + migrations.AddField( + model_name='vendor', + name='public', + field=models.BooleanField(default=True), + preserve_default=False, + ), + migrations.AddField( + model_name='vfc', + name='company', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, + to='engagementmanager.Vendor'), + ), + migrations.AlterField( + model_name='engagement', + name='target_completion_date', + field=models.DateField( + blank=True, default=engagementmanager.models.get_default_target_completion_date, null=True), + ), + migrations.AlterField( + model_name='iceuser', + name='temp_password', + field=models.CharField(blank=True, default=None, max_length=256, null=True), + ), + migrations.AddField( + model_name='vf', + name='deployment_target_sites', + field=models.ManyToManyField(blank=True, default=None, related_name='DeployTarget_sites', + to='engagementmanager.DeploymentTargetSite'), + ), + ] diff --git a/django/engagementmanager/migrations/0006_auto_20160825_0644.py b/django/engagementmanager/migrations/0006_auto_20160825_0644.py new file mode 100755 index 0000000..285631d --- /dev/null +++ b/django/engagementmanager/migrations/0006_auto_20160825_0644.py @@ -0,0 +1,237 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-25 06:44 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0005_auto_20160815_1248'), + ] + + operations = [ + migrations.CreateModel( + name='Checklist', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='checklist name')), + ('state', models.CharField(choices=[(b'(4,)', b'approval'), (b'(7,)', b'archive'), (b'(1,)', b'automation'), (b'(6,)', b'closed'), ( + b'(5,)', b'handoff'), (b'(3,)', b'peer_review'), (b'8', b'pending'), (b'(2,)', b'review')], default=b'automation', max_length=36)), + ('validation_cycle', models.IntegerField(verbose_name='validation cycle')), + ('weight', models.FloatField(default=0, verbose_name='checklist weight')), + ('associated_files', models.TextField(verbose_name='list of files from gitlab')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + related_name='checklist_creator', to='engagementmanager.IceUser')), + ], + options={ + 'db_table': 'ice_checklist', + }, + ), + migrations.CreateModel( + name='ChecklistAuditLog', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('category', models.CharField(max_length=255)), + ('description', models.TextField()), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ('checklist', models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Checklist')), + ('creator', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUser')), + ], + options={ + 'db_table': 'ice_checklist_audit_log', + }, + ), + migrations.CreateModel( + name='ChecklistDecision', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('review_value', models.CharField(choices=[ + (b'(1,)', b'approved'), (b'(2,)', b'denied'), (b'4', b'na'), (b'(3,)', b'not_relevant')], max_length=36)), + ('peer_review_value', models.CharField(choices=[ + (b'(1,)', b'approved'), (b'(2,)', b'denied'), (b'4', b'na'), (b'(3,)', b'not_relevant')], max_length=36)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ('checklist', models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Checklist')), + ], + options={ + 'db_table': 'ice_checklist_decision', + }, + ), + migrations.CreateModel( + name='ChecklistLineItem', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='line name')), + ('weight', models.FloatField(verbose_name='line weight')), + ('description', models.TextField(verbose_name='line description')), + ('line_type', models.CharField(choices=[(b'(1,)', b'auto'), + (b'2', b'manual')], default=b'auto', max_length=36)), + ('validation_instructions', models.TextField(verbose_name='line validation instructions')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ], + options={ + 'db_table': 'ice_checklist_line_item', + }, + ), + migrations.CreateModel( + name='ChecklistSection', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='section name')), + ('weight', models.FloatField(verbose_name='checklist weight')), + ('description', models.TextField(verbose_name='section description')), + ('validation_instructions', models.TextField(verbose_name='section validation instructions')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ('parent_section', models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.ChecklistSection')), + ], + options={ + 'db_table': 'ice_checklist_section', + }, + ), + migrations.CreateModel( + name='ChecklistTemplate', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='template name')), + ('category', models.CharField(choices=[ + (b'3', b'glance'), (b'(2,)', b'heat'), (b'(1,)', b'overall')], default=b'overall', max_length=36)), + ('version', models.IntegerField(verbose_name='template version')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='creation time')), + ('update_time', models.DateTimeField(blank=True, null=True, verbose_name='last update time')), + ], + options={ + 'db_table': 'ice_checklist_template', + }, + ), + migrations.AddField( + model_name='engagement', + name='peer_reviewer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Engagement_peer_reviewer', to='engagementmanager.IceUser'), + ), + migrations.AddField( + model_name='nextstep', + name='assignees', + field=models.ManyToManyField(related_name='assignees', to='engagementmanager.IceUser'), + ), + migrations.AddField( + model_name='nextstep', + name='due_date', + field=models.DateField(null=True, verbose_name='due_date'), + ), + migrations.AddField( + model_name='nextstep', + name='files', + field=models.TextField(null=True, verbose_name='list of files'), + ), + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[(b'6', b'change_checklist_state'), (b'3', b'eng_validation_request'), ( + b'4', b'next_steps'), (b'2', b'ssh_key_added'), (b'1', b'user_joined_eng'), (b'5', b'vfc')], max_length=36), + ), + migrations.AddField( + model_name='checklistsection', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, + to='engagementmanager.ChecklistTemplate'), + ), + migrations.AddField( + model_name='checklistlineitem', + name='section', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.ChecklistSection'), + ), + migrations.AddField( + model_name='checklistlineitem', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.ChecklistTemplate'), + ), + migrations.AddField( + model_name='checklistdecision', + name='lineitem', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.ChecklistLineItem'), + ), + migrations.AddField( + model_name='checklistdecision', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.ChecklistTemplate'), + ), + migrations.AddField( + model_name='checklistauditlog', + name='decision', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.ChecklistDecision'), + ), + migrations.AddField( + model_name='checklist', + name='engagement', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Engagement'), + ), + migrations.AddField( + model_name='checklist', + name='owner', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + related_name='checklist_owner', to='engagementmanager.IceUser'), + ), + migrations.AddField( + model_name='checklist', + name='template', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, + to='engagementmanager.ChecklistTemplate'), + ), + ] diff --git a/django/engagementmanager/migrations/0007_auto_20160922_0421.py b/django/engagementmanager/migrations/0007_auto_20160922_0421.py new file mode 100755 index 0000000..655f30d --- /dev/null +++ b/django/engagementmanager/migrations/0007_auto_20160922_0421.py @@ -0,0 +1,70 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-22 04:21 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0006_auto_20160825_0644'), + ] + + operations = [ + migrations.CreateModel( + name='ECOMPRelease', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=45)), + ], + options={ + 'db_table': 'ice_ecomp_release', + }, + ), + migrations.AddField( + model_name='vf', + name='ecomp_release', + field=models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.SET_NULL, to='engagementmanager.ECOMPRelease'), + ), + ] diff --git a/django/engagementmanager/migrations/0008_auto_20161009_1210.py b/django/engagementmanager/migrations/0008_auto_20161009_1210.py new file mode 100755 index 0000000..ce6ddcc --- /dev/null +++ b/django/engagementmanager/migrations/0008_auto_20161009_1210.py @@ -0,0 +1,74 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-10-09 12:10 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0007_auto_20160922_0421'), + ] + + operations = [ + migrations.CreateModel( + name='RecentEngagement', + fields=[ + ('uuid', models.CharField(max_length=64, primary_key=True, serialize=False)), + ('user_uuid', models.CharField(max_length=64)), + ('action_type', models.CharField(choices=[(b'(3,)', b'GOT_OWNERSHIP_OVER_ENGAGEMENT'), (b'(1,)', b'JOINED_TO_ENGAGEMENT'), ( + b'(4,)', b'NAVIGATED_INTO_ENGAGEMENT'), (b'(2,)', b'NEXT_STEP_ASSIGNED')], max_length=36)), + ('last_update', models.DateTimeField(default=django.utils.timezone.now, verbose_name='update time')), + ('vf', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.VF')), + ], + options={ + 'db_table': 'ice_recent_engagement', + }, + ), + migrations.AddField( + model_name='engagement', + name='starred_engagement', + field=models.ManyToManyField(to='engagementmanager.IceUser'), + ), + ] diff --git a/django/engagementmanager/migrations/0009_auto_20161018_0740.py b/django/engagementmanager/migrations/0009_auto_20161018_0740.py new file mode 100755 index 0000000..5536536 --- /dev/null +++ b/django/engagementmanager/migrations/0009_auto_20161018_0740.py @@ -0,0 +1,65 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-10-18 07:40 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0008_auto_20161009_1210'), + ] + + operations = [ + migrations.AlterField( + model_name='checklist', + name='state', + field=models.CharField(choices=[(b'(4,)', b'approval'), (b'(7,)', b'archive'), (b'(1,)', b'automation'), (b'(6,)', b'closed'), ( + b'(5,)', b'handoff'), (b'(3,)', b'peer_review'), (b'8', b'pending'), (b'(2,)', b'review')], default=b'pending', max_length=36), + ), + migrations.AlterField( + model_name='recentengagement', + name='action_type', + field=models.CharField(choices=[(b'(3,)', b'GOT_OWNERSHIP_OVER_ENGAGEMENT'), (b'(1,)', b'JOINED_TO_ENGAGEMENT'), ( + b'(4,)', b'NAVIGATED_INTO_ENGAGEMENT'), (b'(5,)', b'NEW_VF_CREATED'), (b'(2,)', b'NEXT_STEP_ASSIGNED')], max_length=36), + ), + ] diff --git a/django/engagementmanager/migrations/0010_auto_20161025_0838.py b/django/engagementmanager/migrations/0010_auto_20161025_0838.py new file mode 100755 index 0000000..19f8db6 --- /dev/null +++ b/django/engagementmanager/migrations/0010_auto_20161025_0838.py @@ -0,0 +1,106 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-10-25 08:38 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0009_auto_20161018_0740'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[(b'change_checklist_state', b'change_checklist_state'), (b'eng_validation_request', b'eng_validation_request'), ( + b'next_steps', b'next_steps'), (b'ssh_key_added', b'ssh_key_added'), (b'user_joined_eng', b'user_joined_eng'), (b'vfc', b'vfc')], max_length=36), + ), + migrations.AlterField( + model_name='checklist', + name='state', + field=models.CharField(choices=[(b'approval', b'approval'), (b'archive', b'archive'), (b'automation', b'automation'), (b'closed', b'closed'), ( + b'handoff', b'handoff'), (b'peer_review', b'peer_review'), (b'pending', b'pending'), (b'review', b'review')], default=b'pending', max_length=36), + ), + migrations.AlterField( + model_name='checklistdecision', + name='peer_review_value', + field=models.CharField(choices=[(b'approved', b'approved'), (b'denied', b'denied'), + (b'na', b'na'), (b'not_relevant', b'not_relevant')], max_length=36), + ), + migrations.AlterField( + model_name='checklistdecision', + name='review_value', + field=models.CharField(choices=[(b'approved', b'approved'), (b'denied', b'denied'), + (b'na', b'na'), (b'not_relevant', b'not_relevant')], max_length=36), + ), + migrations.AlterField( + model_name='checklistlineitem', + name='line_type', + field=models.CharField(choices=[(b'auto', b'auto'), (b'manual', b'manual')], + default=b'auto', max_length=36), + ), + migrations.AlterField( + model_name='checklisttemplate', + name='category', + field=models.CharField(choices=[(b'glance', b'glance'), (b'heat', b'heat'), + (b'overall', b'overall')], default=b'overall', max_length=36), + ), + migrations.AlterField( + model_name='engagement', + name='starred_engagement', + field=models.ManyToManyField(blank=True, to='engagementmanager.IceUser'), + ), + migrations.AlterField( + model_name='nextstep', + name='next_step_type', + field=models.CharField(choices=[(b'add_contact_person', b'add_contact_person'), (b'el_handoff', b'el_handoff'), (b'set_ssh', b'set_ssh'), ( + b'submit_vf_package', b'submit_vf_package'), (b'trial_agreements', b'trial_agreements'), (b'user_defined', b'user_defined')], default=b'user_defined', max_length=36), + ), + migrations.AlterField( + model_name='recentengagement', + name='action_type', + field=models.CharField(choices=[(b'GOT_OWNERSHIP_OVER_ENGAGEMENT', b'GOT_OWNERSHIP_OVER_ENGAGEMENT'), (b'JOINED_TO_ENGAGEMENT', b'JOINED_TO_ENGAGEMENT'), ( + b'NAVIGATED_INTO_ENGAGEMENT', b'NAVIGATED_INTO_ENGAGEMENT'), (b'NEW_VF_CREATED', b'NEW_VF_CREATED'), (b'NEXT_STEP_ASSIGNED', b'NEXT_STEP_ASSIGNED')], max_length=36), + ), + ] diff --git a/django/engagementmanager/migrations/0011_auto_20161109_0811.py b/django/engagementmanager/migrations/0011_auto_20161109_0811.py new file mode 100755 index 0000000..9bcf50c --- /dev/null +++ b/django/engagementmanager/migrations/0011_auto_20161109_0811.py @@ -0,0 +1,81 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-09 08:11 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0010_auto_20161025_0838'), + ] + + operations = [ + migrations.AlterField( + model_name='engagement', + name='engagement_manual_id', + field=models.CharField(max_length=36), + ), + migrations.AlterField( + model_name='engagement', + name='starred_engagement', + field=models.ManyToManyField(blank=True, default=None, to='engagementmanager.IceUser'), + ), + migrations.AlterField( + model_name='vf', + name='ecomp_release', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.ECOMPRelease'), + ), + migrations.AlterField( + model_name='vf', + name='engagement', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.Engagement'), + ), + migrations.AlterField( + model_name='vf', + name='git_repo_url', + field=models.CharField(default='', max_length=512), + preserve_default=False, + ), + ] diff --git a/django/engagementmanager/migrations/0012_auto_20161109_0822.py b/django/engagementmanager/migrations/0012_auto_20161109_0822.py new file mode 100755 index 0000000..79214dc --- /dev/null +++ b/django/engagementmanager/migrations/0012_auto_20161109_0822.py @@ -0,0 +1,82 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-09 08:22 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0011_auto_20161109_0811'), + ] + + operations = [ + migrations.AddField( + model_name='engagement', + name='reviewer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Engagement_el_reviewer', to='engagementmanager.IceUser'), + ), + migrations.AlterField( + model_name='engagement', + name='engagement_manual_id', + field=models.CharField(default=-1, max_length=36), + ), + migrations.AlterField( + model_name='nextstep', + name='state', + field=models.CharField(choices=[(b'Completed', b'Completed'), (b'Confirmed', + b'Confirmed'), (b'TODO', b'TODO')], max_length=15), + ), + migrations.AlterField( + model_name='vf', + name='engagement', + field=models.ForeignKey(default=-1, on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.Engagement'), + ), + migrations.AlterField( + model_name='vf', + name='git_repo_url', + field=models.CharField(default=-1, max_length=512), + ), + ] diff --git a/django/engagementmanager/migrations/0013_auto_20161128_1159.py b/django/engagementmanager/migrations/0013_auto_20161128_1159.py new file mode 100755 index 0000000..06a55c1 --- /dev/null +++ b/django/engagementmanager/migrations/0013_auto_20161128_1159.py @@ -0,0 +1,99 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-28 09:59 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0012_auto_20161109_0822'), + ] + + operations = [ + migrations.AddField( + model_name='engagement', + name='active_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='active time'), + ), + migrations.AddField( + model_name='engagement', + name='aic_instantiation_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='aic instantiation time'), + ), + migrations.AddField( + model_name='engagement', + name='asdc_onboarding_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='asdc onboarding time'), + ), + migrations.AddField( + model_name='engagement', + name='completed_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='completed time'), + ), + migrations.AddField( + model_name='engagement', + name='heat_validated_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='heat validated time'), + ), + migrations.AddField( + model_name='engagement', + name='image_scan_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='image scan time'), + ), + migrations.AddField( + model_name='engagement', + name='intake_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='intake time'), + ), + migrations.AddField( + model_name='engagement', + name='started_state_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='started state time'), + ), + migrations.AddField( + model_name='engagement', + name='validated_time', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='validated time'), + ), + ] diff --git a/django/engagementmanager/migrations/0014_auto_20161129_1145.py b/django/engagementmanager/migrations/0014_auto_20161129_1145.py new file mode 100755 index 0000000..ee4efd4 --- /dev/null +++ b/django/engagementmanager/migrations/0014_auto_20161129_1145.py @@ -0,0 +1,104 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-11-29 09:45 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0013_auto_20161128_1159'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[(b'change_checklist_state', b'change_checklist_state'), (b'eng_validation_request', b'eng_validation_request'), (b'next_steps', b'next_steps'), (b'ssh_key_added', b'ssh_key_added'), ( + b'test_finished_event', b'test_finished_event'), (b'user_joined_eng', b'user_joined_eng'), (b'vf_provisioing_event', b'vf_provisioing_event'), (b'vfc', b'vfc')], max_length=36), + ), + migrations.AlterField( + model_name='engagement', + name='active_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='active time'), + ), + migrations.AlterField( + model_name='engagement', + name='aic_instantiation_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='aic instantiation time'), + ), + migrations.AlterField( + model_name='engagement', + name='asdc_onboarding_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='asdc onboarding time'), + ), + migrations.AlterField( + model_name='engagement', + name='completed_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='completed time'), + ), + migrations.AlterField( + model_name='engagement', + name='heat_validated_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='heat validated time'), + ), + migrations.AlterField( + model_name='engagement', + name='image_scan_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='image scan time'), + ), + migrations.AlterField( + model_name='engagement', + name='intake_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='intake time'), + ), + migrations.AlterField( + model_name='engagement', + name='started_state_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='started state time'), + ), + migrations.AlterField( + model_name='engagement', + name='validated_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='validated time'), + ), + ] diff --git a/django/engagementmanager/migrations/0015_engagementstatus.py b/django/engagementmanager/migrations/0015_engagementstatus.py new file mode 100755 index 0000000..84eee4d --- /dev/null +++ b/django/engagementmanager/migrations/0015_engagementstatus.py @@ -0,0 +1,71 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-12-07 09:15 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0014_auto_20161129_1145'), + ] + + operations = [ + migrations.CreateModel( + name='EngagementStatus', + fields=[ + ('uuid', models.CharField(max_length=64, primary_key=True, serialize=False)), + ('description', models.CharField(max_length=256)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now)), + ('update_time', models.DateTimeField(default=django.utils.timezone.now)), + ('creator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='status_creator', to='engagementmanager.IceUser')), + ('engagement', models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Engagement')), + ], + options={ + 'db_table': 'ice_engagement_status', + }, + ), + ] diff --git a/django/engagementmanager/migrations/0016_auto_20161208_0842.py b/django/engagementmanager/migrations/0016_auto_20161208_0842.py new file mode 100755 index 0000000..92d1518 --- /dev/null +++ b/django/engagementmanager/migrations/0016_auto_20161208_0842.py @@ -0,0 +1,59 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-12-08 08:42 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0015_engagementstatus'), + ] + + operations = [ + migrations.AlterField( + model_name='engagement', + name='engagement_stage', + field=models.CharField(choices=[(b'Active', b'Active'), (b'Completed', b'Completed'), + (b'Intake', b'Intake'), (b'Validated', b'Validated')], default=b'Intake', max_length=15), + ), + ] diff --git a/django/engagementmanager/migrations/0017_auto_20161215_1535.py b/django/engagementmanager/migrations/0017_auto_20161215_1535.py new file mode 100755 index 0000000..c0adc38 --- /dev/null +++ b/django/engagementmanager/migrations/0017_auto_20161215_1535.py @@ -0,0 +1,74 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-12-15 13:35 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0016_auto_20161208_0842'), + ] + + operations = [ + migrations.CreateModel( + name='Invitation', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False)), + ('engagement_uuid', models.CharField(db_index=True, max_length=64)), + ('invited_by_user_uuid', models.CharField(db_index=True, max_length=64)), + ('email', models.CharField(max_length=255)), + ('invitation_token', models.CharField(max_length=1024)), + ('accepted', models.BooleanField(default=False)), + ('create_time', models.DateTimeField( + default=django.utils.timezone.now, verbose_name='invitation creation time')), + ], + options={ + 'db_table': 'ice_invitation', + }, + ), + migrations.AlterUniqueTogether( + name='invitation', + unique_together=set([('engagement_uuid', 'email')]), + ), + ] diff --git a/django/engagementmanager/migrations/0018_set_old_notif_true.py b/django/engagementmanager/migrations/0018_set_old_notif_true.py new file mode 100755 index 0000000..76e8265 --- /dev/null +++ b/django/engagementmanager/migrations/0018_set_old_notif_true.py @@ -0,0 +1,54 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-12-29 13:49 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0017_auto_20161215_1535'), + ] + + operations = [ + migrations.RunSQL("update ice_notification SET is_sent = 't' where is_sent = 'f';"), + ] diff --git a/django/engagementmanager/migrations/0019_auto_20170104_1715.py b/django/engagementmanager/migrations/0019_auto_20170104_1715.py new file mode 100755 index 0000000..329ffa3 --- /dev/null +++ b/django/engagementmanager/migrations/0019_auto_20170104_1715.py @@ -0,0 +1,59 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2017-01-04 17:15 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0018_set_old_notif_true'), + ] + + operations = [ + migrations.AlterField( + model_name='engagement', + name='engagement_stage', + field=models.CharField(choices=[(b'Active', b'Active'), (b'Archived', b'Archived'), (b'Completed', b'Completed'), ( + b'Intake', b'Intake'), (b'Validated', b'Validated')], default=b'Intake', max_length=15), + ), + ] diff --git a/django/engagementmanager/migrations/0020_add_indexes_20170108.py b/django/engagementmanager/migrations/0020_add_indexes_20170108.py new file mode 100755 index 0000000..2b71e1e --- /dev/null +++ b/django/engagementmanager/migrations/0020_add_indexes_20170108.py @@ -0,0 +1,109 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2017-01-12 08:39 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0019_auto_20170104_1715'), + ] + + operations = [ + migrations.DeleteModel( + name='ContactRequest', + ), + migrations.DeleteModel( + name='EngagementRequest', + ), + migrations.AlterField( + model_name='engagement', + name='engagement_manual_id', + field=models.CharField(db_index=True, default=-1, max_length=36), + ), + migrations.AlterField( + model_name='engagement', + name='engagement_stage', + field=models.CharField(choices=[(b'Active', b'Active'), (b'Archived', b'Archived'), (b'Completed', b'Completed'), ( + b'Intake', b'Intake'), (b'Validated', b'Validated')], db_index=True, default=b'Intake', max_length=15), + ), + migrations.AlterField( + model_name='iceuser', + name='email', + field=models.EmailField(db_index=True, max_length=254, unique=True, verbose_name='email'), + ), + migrations.AlterField( + model_name='invitation', + name='invitation_token', + field=models.CharField(db_index=True, max_length=1024), + ), + migrations.AlterField( + model_name='vf', + name='engagement', + field=models.OneToOneField(default=-1, on_delete=django.db.models.deletion.CASCADE, + to='engagementmanager.Engagement'), + ), + migrations.AlterField( + model_name='vf', + name='name', + field=models.CharField(db_index=True, max_length=100), + ), + migrations.AlterField( + model_name='vfc', + name='name', + field=models.CharField(db_index=True, max_length=100), + ), + migrations.AlterIndexTogether( + name='activity', + index_together=set([('engagement', 'activity_owner')]), + ), + migrations.AlterIndexTogether( + name='nextstep', + index_together=set([('engagement_stage', 'owner')]), + ), + migrations.AlterIndexTogether( + name='notification', + index_together=set([('user', 'is_read')]), + ), + ] diff --git a/django/engagementmanager/migrations/0021_generate_excel_overview_sheet_procedure_20170110.py b/django/engagementmanager/migrations/0021_generate_excel_overview_sheet_procedure_20170110.py new file mode 100755 index 0000000..b902df4 --- /dev/null +++ b/django/engagementmanager/migrations/0021_generate_excel_overview_sheet_procedure_20170110.py @@ -0,0 +1,65 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from __future__ import unicode_literals + +import os + +from django.db import migrations, connection + +import engagementmanager + + +def forwards(apps, schema_editor): + if not schema_editor.connection.alias == 'default': + return + + cursor = connection.cursor() + cursor.execute(open(os.path.join(os.path.dirname(engagementmanager.__file__), + 'sql-scripts/generate_excel_overview_sheet_procedure.sql'), "r").read()) + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0020_add_indexes_20170108'), + ] + + operations = [ + migrations.RunPython(forwards), + ] diff --git a/django/engagementmanager/migrations/0022_auto_20170118_1520.py b/django/engagementmanager/migrations/0022_auto_20170118_1520.py new file mode 100755 index 0000000..b90451b --- /dev/null +++ b/django/engagementmanager/migrations/0022_auto_20170118_1520.py @@ -0,0 +1,275 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-01-18 15:20 +from __future__ import unicode_literals + +import logging + +from django.conf import settings +import django.contrib.auth.models +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +logger = logging.getLogger('ice.logger') + + +def create_user_for_pre_user_profiles(apps, schema_editor): + CustomUser = apps.get_model("engagementmanager", "CustomUser") + IceUserProfile = apps.get_model("engagementmanager", "IceUserProfile") + users_list = IceUserProfile.objects.filter(user=None) + count = 0 + for profile in users_list: + try: + custom_user, created = CustomUser.objects.get_or_create(username=profile.email) + custom_user.is_active = profile.is_active + custom_user.email = profile.email + custom_user.activation_token = profile.activation_token + custom_user.password = profile.password + custom_user.activation_token_create_time = profile.activation_token_create_time + custom_user.save() + profile.user = custom_user + profile.save() + + except Exception as e: + logger.error("migrations fail, error:") + logger.error(e.message) + + +class Migration(migrations.Migration): + + dependencies = [ + # ('auth', '0009_auto_20170118_0740'), + ('engagementmanager', '0021_generate_excel_overview_sheet_procedure_20170110'), + ] + + operations = [ + migrations.CreateModel( + name='CustomUser', + fields=[ + ('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, + parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), + ('activation_token', models.CharField(max_length=128, null=True, unique=True)), + ('activation_token_create_time', models.DateTimeField( + default=django.utils.timezone.now, null=True, verbose_name='activation_token_create_time')), + ('temp_password', models.CharField(blank=True, default=None, max_length=256, null=True)), + ], + options={ + 'abstract': False, + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + }, + bases=('auth.user',), + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.AlterModelTable('IceUser', 'ice_user_profile'), + migrations.RenameModel('IceUser', 'IceUserProfile'), + migrations.AddField( + model_name='IceUserProfile', + name='user', + field=models.OneToOneField(null=True, on_delete=django.db.models.CASCADE, to='engagementmanager.CustomUser') + ), + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[(b'user_joined_eng', b'user_joined_eng'), (b'ssh_key_added', b'ssh_key_added'), (b'eng_validation_request', b'eng_validation_request'), (b'next_steps', b'next_steps'), ( + b'vfc', b'vfc'), (b'change_checklist_state', b'change_checklist_state'), (b'vf_provisioing_event', b'vf_provisioing_event'), (b'test_finished_event', b'test_finished_event')], max_length=36), + ), + migrations.AlterField( + model_name='checklist', + name='state', + field=models.CharField(choices=[(b'pending', b'pending'), (b'automation', b'automation'), (b'review', b'review'), (b'peer_review', b'peer_review'), ( + b'approval', b'approval'), (b'handoff', b'handoff'), (b'closed', b'closed'), (b'archive', b'archive')], default=b'pending', max_length=36), + ), + migrations.AlterField( + model_name='checklistdecision', + name='peer_review_value', + field=models.CharField(choices=[(b'na', b'na'), (b'approved', b'approved'), + (b'denied', b'denied'), (b'not_relevant', b'not_relevant')], max_length=36), + ), + migrations.AlterField( + model_name='checklistdecision', + name='review_value', + field=models.CharField(choices=[(b'na', b'na'), (b'approved', b'approved'), + (b'denied', b'denied'), (b'not_relevant', b'not_relevant')], max_length=36), + ), + migrations.AlterField( + model_name='checklistlineitem', + name='line_type', + field=models.CharField( + choices=[(b'manual', b'manual'), (b'auto', b'auto')], default=b'auto', max_length=36), + ), + migrations.AlterField( + model_name='checklisttemplate', + name='category', + field=models.CharField(choices=[(b'glance', b'glance'), (b'instantiation', b'instantiation'), ( + b'asdc', b'asdc'), (b'overall', b'overall'), (b'heat', b'heat')], default=b'overall', max_length=36), + ), + migrations.AlterField( + model_name='engagement', + name='engagement_stage', + field=models.CharField(choices=[(b'Archived', b'Archived'), (b'Intake', b'Intake'), (b'Active', b'Active'), ( + b'Validated', b'Validated'), (b'Completed', b'Completed')], db_index=True, default=b'Intake', max_length=15), + ), + + migrations.AlterField( + model_name='nextstep', + name='next_step_type', + field=models.CharField(choices=[(b'user_defined', b'user_defined'), (b'set_ssh', b'set_ssh'), (b'trial_agreements', b'trial_agreements'), ( + b'add_contact_person', b'add_contact_person'), (b'submit_vf_package', b'submit_vf_package'), (b'el_handoff', b'el_handoff')], default=b'user_defined', max_length=36), + ), + + migrations.AlterField( + model_name='nextstep', + name='state', + field=models.CharField( + choices=[(b'Confirmed', b'Confirmed'), (b'TODO', b'TODO'), (b'Completed', b'Completed')], max_length=15), + ), + migrations.AlterField( + model_name='recentengagement', + name='action_type', + field=models.CharField(choices=[(b'JOINED_TO_ENGAGEMENT', b'JOINED_TO_ENGAGEMENT'), (b'NEXT_STEP_ASSIGNED', b'NEXT_STEP_ASSIGNED'), ( + b'GOT_OWNERSHIP_OVER_ENGAGEMENT', b'GOT_OWNERSHIP_OVER_ENGAGEMENT'), (b'NAVIGATED_INTO_ENGAGEMENT', b'NAVIGATED_INTO_ENGAGEMENT'), (b'NEW_VF_CREATED', b'NEW_VF_CREATED')], max_length=36), + ), + # migrations.DeleteModel( + # name='IceUser', + # ), + migrations.RunPython(create_user_for_pre_user_profiles), + migrations.AlterField( + model_name='notification', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='vfc', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Vfc_creator', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='nextstep', + name='owner', + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='engagement', + name='engagement_team', + field=models.ManyToManyField(related_name='members', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='engagement', + name='contact_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Engagement_contact_user', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='engagement', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Engagement_creator', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='checklistauditlog', + name='creator', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='engagement', + name='peer_reviewer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Engagement_peer_reviewer', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='engagement', + name='reviewer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='Engagement_el_reviewer', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='engagement', + name='starred_engagement', + field=models.ManyToManyField(blank=True, default=None, to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='engagementstatus', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='status_creator', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='nextstep', + name='assignees', + field=models.ManyToManyField(related_name='assignees', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='nextstep', + name='creator', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, + related_name='NextStep_creator', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='nextstep', + name='last_updater', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, + related_name='NextStep_last_updater', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='activity', + name='activity_owner', + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='checklist', + name='creator', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + related_name='checklist_creator', to='engagementmanager.IceUserProfile'), + ), + migrations.AlterField( + model_name='checklist', + name='owner', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, + related_name='checklist_owner', to='engagementmanager.IceUserProfile'), + ), + ] diff --git a/django/engagementmanager/migrations/0023_auto_20170123_1445.py b/django/engagementmanager/migrations/0023_auto_20170123_1445.py new file mode 100755 index 0000000..cd01832 --- /dev/null +++ b/django/engagementmanager/migrations/0023_auto_20170123_1445.py @@ -0,0 +1,108 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-01-23 14:45 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0022_auto_20170118_1520'), + ] + + operations = [ + migrations.AlterModelOptions( + name='customuser', + options={}, + ), + migrations.RemoveField( + model_name='iceuserprofile', + name='activation_token', + ), + migrations.RemoveField( + model_name='iceuserprofile', + name='activation_token_create_time', + ), + migrations.RemoveField( + model_name='iceuserprofile', + name='is_active', + ), + migrations.RemoveField( + model_name='iceuserprofile', + name='last_login', + ), + migrations.RemoveField( + model_name='iceuserprofile', + name='password', + ), + migrations.RemoveField( + model_name='iceuserprofile', + name='temp_password', + ), + migrations.AlterField( + model_name='iceuserprofile', + name='company', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, + to='engagementmanager.Vendor'), + ), + migrations.AlterField( + model_name='iceuserprofile', + name='is_att_contact', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='iceuserprofile', + name='role', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, + to='engagementmanager.Role'), + ), + migrations.AlterField( + model_name='iceuserprofile', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.CustomUser'), + ), + migrations.AlterModelTable( + name='customuser', + table='ice_custom_user', + ), + ] diff --git a/django/engagementmanager/migrations/0024_auto_20170227_1224.py b/django/engagementmanager/migrations/0024_auto_20170227_1224.py new file mode 100755 index 0000000..3481eb5 --- /dev/null +++ b/django/engagementmanager/migrations/0024_auto_20170227_1224.py @@ -0,0 +1,64 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2017-02-27 12:24 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0023_auto_20170123_1445'), + ] + + operations = [ + migrations.AddField( + model_name='engagement', + name='archive_reason', + field=models.TextField(default=None, null=True), + ), + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[(b'user_joined_eng', b'user_joined_eng'), (b'ssh_key_added', b'ssh_key_added'), (b'eng_validation_request', b'eng_validation_request'), (b'next_steps', b'next_steps'), (b'vfc', b'vfc'), ( + b'change_checklist_state', b'change_checklist_state'), (b'vf_provisioing_event', b'vf_provisioing_event'), (b'test_finished_event', b'test_finished_event'), (b'change_engagement_stage', b'change_engagement_stage')], max_length=36), + ), + ] diff --git a/django/engagementmanager/migrations/0025_change_nextsteps_to_new_state.py b/django/engagementmanager/migrations/0025_change_nextsteps_to_new_state.py new file mode 100755 index 0000000..bfec64d --- /dev/null +++ b/django/engagementmanager/migrations/0025_change_nextsteps_to_new_state.py @@ -0,0 +1,54 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0024_auto_20170227_1224'), + ] + + operations = [ + migrations.RunSQL("update ice_next_step set state = 'Incomplete' where state = 'TODO';"), + migrations.RunSQL("update ice_next_step set state = 'Completed' where state = 'Confirmed';"), + ] diff --git a/django/engagementmanager/migrations/0026_add_slack_handle_to_ice_user_profile.py b/django/engagementmanager/migrations/0026_add_slack_handle_to_ice_user_profile.py new file mode 100755 index 0000000..489b6ce --- /dev/null +++ b/django/engagementmanager/migrations/0026_add_slack_handle_to_ice_user_profile.py @@ -0,0 +1,57 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0025_change_nextsteps_to_new_state'), + ] + + operations = [ + migrations.AddField( + model_name='iceuserprofile', + name='slack_handle', + field=models.CharField(blank=True, default=None, max_length=64, null=True), + ), + ] diff --git a/django/engagementmanager/migrations/0027_add_version_to_vf.py b/django/engagementmanager/migrations/0027_add_version_to_vf.py new file mode 100755 index 0000000..3bd618e --- /dev/null +++ b/django/engagementmanager/migrations/0027_add_version_to_vf.py @@ -0,0 +1,58 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-04-06 08:05 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0026_add_slack_handle_to_ice_user_profile'), + ] + + operations = [ + migrations.AddField( + model_name='vf', + name='version', + field=models.CharField(db_index=True, max_length=100, null=True), + ) + ] diff --git a/django/engagementmanager/migrations/0028_auto_20170425_1310.py b/django/engagementmanager/migrations/0028_auto_20170425_1310.py new file mode 100755 index 0000000..68e15f5 --- /dev/null +++ b/django/engagementmanager/migrations/0028_auto_20170425_1310.py @@ -0,0 +1,111 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-04-25 13:10 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0027_add_version_to_vf'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[('user_joined_eng', 'user_joined_eng'), ('ssh_key_added', 'ssh_key_added'), ('eng_validation_request', 'eng_validation_request'), ('next_steps', 'next_steps'), ('vfc', 'vfc'), ( + 'change_checklist_state', 'change_checklist_state'), ('vf_provisioing_event', 'vf_provisioing_event'), ('test_finished_event', 'test_finished_event'), ('change_engagement_stage', 'change_engagement_stage')], max_length=36), + ), + migrations.AlterField( + model_name='checklist', + name='state', + field=models.CharField(choices=[('automation', 'automation'), ('review', 'review'), ('peer_review', 'peer_review'), ('approval', 'approval'), ( + 'handoff', 'handoff'), ('closed', 'closed'), ('archive', 'archive'), ('pending', 'pending')], default='pending', max_length=36), + ), + migrations.AlterField( + model_name='checklistdecision', + name='peer_review_value', + field=models.CharField(choices=[('approved', 'approved'), ('denied', 'denied'), + ('not_relevant', 'not_relevant'), ('na', 'na')], max_length=36), + ), + migrations.AlterField( + model_name='checklistdecision', + name='review_value', + field=models.CharField(choices=[('approved', 'approved'), ('denied', 'denied'), + ('not_relevant', 'not_relevant'), ('na', 'na')], max_length=36), + ), + migrations.AlterField( + model_name='checklistlineitem', + name='line_type', + field=models.CharField(choices=[('auto', 'auto'), ('manual', 'manual')], default='auto', max_length=36), + ), + migrations.AlterField( + model_name='checklisttemplate', + name='category', + field=models.CharField(choices=[('overall', 'overall'), ('heat', 'heat'), ('glance', 'glance'), + ('instantiation', 'instantiation'), ('asdc', 'asdc')], default='overall', max_length=36), + ), + migrations.AlterField( + model_name='engagement', + name='engagement_stage', + field=models.CharField(choices=[('Intake', 'Intake'), ('Active', 'Active'), ('Validated', 'Validated'), ( + 'Completed', 'Completed'), ('Archived', 'Archived')], db_index=True, default='Intake', max_length=15), + ), + migrations.AlterField( + model_name='nextstep', + name='next_step_type', + field=models.CharField(choices=[('set_ssh', 'set_ssh'), ('trial_agreements', 'trial_agreements'), ('add_contact_person', 'add_contact_person'), ( + 'submit_vf_package', 'submit_vf_package'), ('el_handoff', 'el_handoff'), ('user_defined', 'user_defined')], default='user_defined', max_length=36), + ), + migrations.AlterField( + model_name='nextstep', + name='state', + field=models.CharField(choices=[('Incomplete', 'Incomplete'), ('Completed', 'Completed')], max_length=15), + ), + migrations.AlterField( + model_name='recentengagement', + name='action_type', + field=models.CharField(choices=[('JOINED_TO_ENGAGEMENT', 'JOINED_TO_ENGAGEMENT'), ('NEXT_STEP_ASSIGNED', 'NEXT_STEP_ASSIGNED'), ('GOT_OWNERSHIP_OVER_ENGAGEMENT', + 'GOT_OWNERSHIP_OVER_ENGAGEMENT'), ('NAVIGATED_INTO_ENGAGEMENT', 'NAVIGATED_INTO_ENGAGEMENT'), ('NEW_VF_CREATED', 'NEW_VF_CREATED')], max_length=36), + ), + ] diff --git a/django/engagementmanager/migrations/0029_auto_20170504_0749.py b/django/engagementmanager/migrations/0029_auto_20170504_0749.py new file mode 100755 index 0000000..f1a4f9a --- /dev/null +++ b/django/engagementmanager/migrations/0029_auto_20170504_0749.py @@ -0,0 +1,73 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-05-04 07:49 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0028_auto_20170425_1310'), + ] + + operations = [ + migrations.AddField( + model_name='deploymenttarget', + name='ui_visibility', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='deploymenttarget', + name='weight', + field=models.IntegerField(default=1), + ), + migrations.AddField( + model_name='ecomprelease', + name='ui_visibility', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='ecomprelease', + name='weight', + field=models.IntegerField(default=1), + ), + ] diff --git a/django/engagementmanager/migrations/0030_engagement_archived_time.py b/django/engagementmanager/migrations/0030_engagement_archived_time.py new file mode 100755 index 0000000..b24f67a --- /dev/null +++ b/django/engagementmanager/migrations/0030_engagement_archived_time.py @@ -0,0 +1,58 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-06-07 08:13 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0029_auto_20170504_0749'), + ] + + operations = [ + migrations.AddField( + model_name='engagement', + name='archived_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='archived time'), + ), + ] diff --git a/django/engagementmanager/migrations/0031_auto_20170620_1312.py b/django/engagementmanager/migrations/0031_auto_20170620_1312.py new file mode 100755 index 0000000..f1956c4 --- /dev/null +++ b/django/engagementmanager/migrations/0031_auto_20170620_1312.py @@ -0,0 +1,64 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-06-20 13:12 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0030_engagement_archived_time'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[('user_joined_eng', 'user_joined_eng'), ('ssh_key_added', 'ssh_key_added'), ('eng_validation_request', 'eng_validation_request'), ('update_next_steps', 'update_next_steps'), ('vfc', 'vfc'), ('change_checklist_state', 'change_checklist_state'), ('vf_provisioning_event', 'vf_provisioning_event'), ('test_finished_event', 'test_finished_event'), ('change_engagement_stage', 'change_engagement_stage'), ('add_next_steps', 'add_next_steps'), ('delete_next_steps', 'delete_next_steps')], max_length=36), + ), + migrations.AlterField( + model_name='activity', + name='engagement', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='engagementmanager.Engagement'), + ), + ] diff --git a/django/engagementmanager/migrations/0032_auto_20170702_1435.py b/django/engagementmanager/migrations/0032_auto_20170702_1435.py new file mode 100755 index 0000000..53e5a22 --- /dev/null +++ b/django/engagementmanager/migrations/0032_auto_20170702_1435.py @@ -0,0 +1,71 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-07-02 14:35 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0031_auto_20170620_1312'), + ] + + operations = [ + migrations.CreateModel( + name='Feedback', + fields=[ + ('uuid', models.CharField(max_length=36, primary_key=True, serialize=False, unique=True)), + ('create_time', models.DateTimeField(default=django.utils.timezone.now)), + ('description', models.TextField(verbose_name='feedback_description')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='engagementmanager.IceUserProfile')), + ], + options={ + 'db_table': 'ice_feedback', + }, + ), + migrations.AlterIndexTogether( + name='feedback', + index_together=set([('user',)]), + ), + ] diff --git a/django/engagementmanager/migrations/0033_auto_20170704_0635.py b/django/engagementmanager/migrations/0033_auto_20170704_0635.py new file mode 100755 index 0000000..c6d1bb6 --- /dev/null +++ b/django/engagementmanager/migrations/0033_auto_20170704_0635.py @@ -0,0 +1,169 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-07-04 06:35 +from __future__ import unicode_literals + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0032_auto_20170702_1435'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='applicationserviceinfrastructure', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, unique=True), + ), + migrations.AlterField( + model_name='checklist', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='checklistauditlog', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='checklistdecision', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='checklistlineitem', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='checklistsection', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='checklisttemplate', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='deploymenttarget', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='deploymenttargetsite', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='ecomprelease', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='engagement', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=64, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='engagementstatus', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=64, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='feedback', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='iceuserprofile', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, unique=True), + ), + migrations.AlterField( + model_name='invitation', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='nextstep', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='notification', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='recentengagement', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=64, primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='role', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, unique=True), + ), + migrations.AlterField( + model_name='vendor', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, unique=True), + ), + migrations.AlterField( + model_name='vf', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True), + ), + migrations.AlterField( + model_name='vfc', + name='uuid', + field=models.CharField(default=uuid.uuid4, max_length=36, primary_key=True, serialize=False, unique=True), + ), + ] diff --git a/django/engagementmanager/migrations/0034_engagement_is_with_files.py b/django/engagementmanager/migrations/0034_engagement_is_with_files.py new file mode 100755 index 0000000..01d15f5 --- /dev/null +++ b/django/engagementmanager/migrations/0034_engagement_is_with_files.py @@ -0,0 +1,58 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-07-13 04:48 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0033_auto_20170704_0635'), + ] + + operations = [ + migrations.AddField( + model_name='engagement', + name='is_with_files', + field=models.BooleanField(default=False), + ), + ] diff --git a/django/engagementmanager/migrations/0035_rgwa_fields.py b/django/engagementmanager/migrations/0035_rgwa_fields.py new file mode 100755 index 0000000..cce62bf --- /dev/null +++ b/django/engagementmanager/migrations/0035_rgwa_fields.py @@ -0,0 +1,68 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-07-25 07:43 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0034_engagement_is_with_files'), + ] + + operations = [ + migrations.AddField( + model_name='iceuserprofile', + name='rgwa_access_key', + field=models.CharField(blank=True, max_length=1024, null=True, unique=True), + ), + migrations.AddField( + model_name='iceuserprofile', + name='rgwa_secret_key', + field=models.CharField(blank=True, max_length=1024, null=True, unique=True), + ), + migrations.AlterField( + model_name='activity', + name='activity_type', + field=models.CharField(choices=[('user_joined_eng', 'user_joined_eng'), ('ssh_key_added', 'ssh_key_added'), ('eng_validation_request', 'eng_validation_request'), ('update_next_steps', 'update_next_steps'), ('vfc', 'vfc'), ('change_checklist_state', 'change_checklist_state'), ('vf_provisioning_event', 'vf_provisioning_event'), ('test_finished_event', 'test_finished_event'), ('change_engagement_stage', 'change_engagement_stage'), ('add_next_steps', 'add_next_steps'), ('delete_next_steps', 'delete_next_steps'), ('notice_empty_engagement', 'notice_empty_engagement')], max_length=36), + ), + ] diff --git a/django/engagementmanager/migrations/0036_auto_20170906_0935.py b/django/engagementmanager/migrations/0036_auto_20170906_0935.py new file mode 100755 index 0000000..7c85b6c --- /dev/null +++ b/django/engagementmanager/migrations/0036_auto_20170906_0935.py @@ -0,0 +1,63 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-09-06 09:35 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('engagementmanager', '0035_rgwa_fields'), + ] + + operations = [ + migrations.RenameField( + model_name='iceuserprofile', + old_name='is_att_contact', + new_name='is_service_provider_contact', + ), + migrations.RenameField( + model_name='vf', + old_name='is_att_internal', + new_name='is_service_provider_internal', + ), + ] diff --git a/django/engagementmanager/migrations/__init__.py b/django/engagementmanager/migrations/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/migrations/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/models.py b/django/engagementmanager/models.py new file mode 100755 index 0000000..71deb84 --- /dev/null +++ b/django/engagementmanager/models.py @@ -0,0 +1,615 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from __future__ import unicode_literals +import uuid +from django.contrib.auth.models import User +from django.db import models +from django.db.models.deletion import SET_NULL +from django.db.models.signals import post_save +from django.utils import timezone +from django.utils.timezone import timedelta +from engagementmanager.service.logging_service import LoggingServiceFactory +from engagementmanager.utils.constants import EngagementStage, ActivityType, NextStepType, CheckListState, CheckListCategory, CheckListDecisionValue, CheckListLineType, \ + RecentEngagementActionType, NextStepState + + +logger = LoggingServiceFactory.get_logger() + + +class Role(models.Model): + uuid = models.CharField(default=uuid.uuid4, max_length=36, unique=True) + name = models.CharField(max_length=36, unique=True) + + def __str__(self): + return self.name + + class Meta: + db_table = "ice_role" + + +class Vendor(models.Model): + uuid = models.CharField(default=uuid.uuid4, max_length=36, unique=True) + name = models.CharField(max_length=100, unique=True) + public = models.BooleanField() + + def __str__(self): + return self.name + + class Meta: + db_table = "ice_vendor" + + +class CustomUser(User): + activation_token = models.CharField(max_length=128, unique=True, null=True) + activation_token_create_time = models.DateTimeField( + 'activation_token_create_time', default=timezone.now, null=True) + temp_password = models.CharField( + max_length=256, null=True, blank=True, default=None) + + def __str__(self): + return self.email + + class Meta: + db_table = "ice_custom_user" + + +class IceUserProfile(models.Model): + user = models.OneToOneField( + CustomUser, null=False, on_delete=models.CASCADE) + uuid = models.CharField(default=uuid.uuid4, max_length=36, unique=True) + company = models.ForeignKey(Vendor, on_delete=models.PROTECT, null=True) + phone_number = models.CharField(max_length=30) + full_name = models.CharField(max_length=30) + role = models.ForeignKey(Role, on_delete=models.PROTECT, null=True) + # although number of expected users<10^5 we prefer to index it + email = models.EmailField('email', unique=True, db_index=True) + create_time = models.DateTimeField('creation time', default=timezone.now) + ssh_public_key = models.CharField( + 'ssh_public_key', max_length=1024, null=True, blank=True) + regular_email_updates = models.BooleanField(default=False) + email_updates_on_every_notification = models.BooleanField(default=True) + email_updates_daily_digest = models.BooleanField(default=False) + is_service_provider_contact = models.BooleanField(default=False) + rgwa_access_key = models.CharField( + max_length=1024, null=True, blank=True, unique=True) + rgwa_secret_key = models.CharField( + max_length=1024, null=True, blank=True, unique=True) + slack_handle = models.CharField( + max_length=64, null=True, blank=True, default=None) + + def __str__(self): + return self.full_name + " - " + self.email + + class Meta: + db_table = "ice_user_profile" + + +def create_user_profile(sender, instance, created, **kwargs): + if created: + user = CustomUser.objects.get(username=instance) + profile, created = IceUserProfile.objects.get_or_create( + user=user, email=instance) + + +post_save.connect(create_user_profile, sender=CustomUser) + + +# Represents Deployment Target Cloud Version. For example name=AIC version=2.0 +class DeploymentTarget(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + name = models.CharField(max_length=45) + version = models.CharField(max_length=100) + weight = models.IntegerField(default=1) + ui_visibility = models.BooleanField(default=True) + + def __str__(self): + return self.name + ", Version: " + self.version + + class Meta: + db_table = "ice_deployment_target" + unique_together = (("name", "version"),) + + +# Represents ECOMPRelease +class ECOMPRelease(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + name = models.CharField(max_length=45) + weight = models.IntegerField(default=1) + ui_visibility = models.BooleanField(default=True) + + def __str__(self): + return self.name + + class Meta: + db_table = "ice_ecomp_release" + + +# Represents Deployment Target site, for example: Willows. It is connected +# to deployment target version +class DeploymentTargetSite(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + name = models.CharField(max_length=45) + + def __str__(self): + return self.name + + class Meta: + db_table = "ice_deployment_target_site" + + +def get_default_target_completion_date(): + return timezone.now() + timedelta(days=16) + + +class Engagement(models.Model): + # no need to index this since index already exists thanks to it PK + # characteristics + uuid = models.CharField( + default=uuid.uuid4, max_length=64, primary_key=True) + engagement_team = models.ManyToManyField( + IceUserProfile, related_name='members') + creator = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, null=True, blank=True, related_name='Engagement_creator') + contact_user = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, null=True, blank=True, related_name='Engagement_contact_user') + engagement_manual_id = models.CharField( + max_length=36, null=False, blank=False, default=-1, db_index=True) # index in favor of dashboard search + progress = models.IntegerField(default=0) + target_completion_date = models.DateField( + null=True, blank=True, default=get_default_target_completion_date) + engagement_stage = models.CharField(max_length=15, default=EngagementStage.Intake.name, choices=EngagementStage.choices( + ), db_index=True) # Can be: Intake, Active, Validated, Completed @UndefinedVariable + create_time = models.DateTimeField('creation time', default=timezone.now) + peer_reviewer = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, null=True, blank=True, related_name='Engagement_peer_reviewer') + reviewer = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, null=True, blank=True, related_name='Engagement_el_reviewer') + starred_engagement = models.ManyToManyField( + IceUserProfile, default=None, blank=True) + heat_validated_time = models.DateTimeField( + 'heat validated time', null=True, blank=True) + image_scan_time = models.DateTimeField( + 'image scan time', null=True, blank=True) + aic_instantiation_time = models.DateTimeField( + 'aic instantiation time', null=True, blank=True) + asdc_onboarding_time = models.DateTimeField( + 'asdc onboarding time', null=True, blank=True) + started_state_time = models.DateTimeField( + 'started state time', null=True, blank=True) + intake_time = models.DateTimeField('intake time', null=True, blank=True) + active_time = models.DateTimeField('active time', null=True, blank=True) + validated_time = models.DateTimeField( + 'validated time', null=True, blank=True) + completed_time = models.DateTimeField( + 'completed time', null=True, blank=True) + archive_reason = models.TextField(default=None, null=True) + archived_time = models.DateTimeField( + 'archived time', null=True, blank=True) + is_with_files = models.BooleanField(default=False) + + def __str__(self): + return " uuid: " + str(self.uuid) + + class Meta: + db_table = "ice_engagement" + + +class EngagementStatus(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=64, primary_key=True) + engagement = models.ForeignKey(Engagement, on_delete=models.PROTECT) + description = models.CharField(max_length=256) + creator = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, null=True, blank=True, related_name='status_creator') + create_time = models.DateTimeField(default=timezone.now) + update_time = models.DateTimeField(default=timezone.now) + + class Meta: + db_table = "ice_engagement_status" + + +class Activity(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, unique=True, primary_key=True) + create_time = models.DateTimeField(default=timezone.now) + description = models.CharField(max_length=512) + is_notification = models.BooleanField(default=False) + engagement = models.ForeignKey( + Engagement, on_delete=models.PROTECT, db_index=True, null=True) + activity_type = models.CharField( + max_length=36, choices=ActivityType.choices()) + activity_owner = models.ForeignKey(IceUserProfile, null=True, blank=True) + metadata = models.CharField(max_length=1024) + + def __str__(self): + return 'Activity created at ' + str(self.create_time) + ', Description: ' + self.description + ', Notification:' + str(self.is_notification) + ', ActivityType=' + str(self.activity_type) + + class Meta: + ordering = ['-create_time'] + db_table = "ice_activity" + # index in favor of pullRecentActivities + index_together = ["engagement", "activity_owner"] + + +class Notification(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, unique=True, primary_key=True) + user = models.ForeignKey(IceUserProfile, on_delete=models.CASCADE) + is_sent = models.BooleanField(default=False) + is_read = models.BooleanField(default=False) + activity = models.ForeignKey(Activity, on_delete=models.CASCADE, null=True) + + def __str__(self): + return str(self.user) + ' ' + str(self.is_sent) + ' ' + str(self.is_read) + + class Meta: + db_table = "ice_notification" + # index in favor of Notification screen (pull_recent_notifications, + # num_of_notifications_for_user) + index_together = ["user", "is_read"] + + +class Feedback(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, unique=True, primary_key=True) + create_time = models.DateTimeField(default=timezone.now) + user = models.ForeignKey(IceUserProfile, null=False) + description = models.TextField('feedback_description') + + def __str__(self): + return 'Feedback created at ' + str(self.create_time) + ' ' + str(self.user) + ', Description: ' + self.description + + class Meta: + db_table = "ice_feedback" + # index in favor of Notification screen (pull_recent_notifications, + # num_of_notifications_for_user) + index_together = ["user"] + + +class ApplicationServiceInfrastructure(models.Model): + name = models.CharField(max_length=100, unique=True) + uuid = models.CharField(default=uuid.uuid4, max_length=36, unique=True) + + def __str__(self): + return self.name + + class Meta: + db_table = "ice_application_service_infrastructure" + unique_together = (('name', 'uuid'),) + + +class VF(models.Model): + # in favor of dashboard search by keyword + name = models.CharField(max_length=100, db_index=True) + # in favor of dashboard search by keyword + version = models.CharField(max_length=100, db_index=True, null=True) + uuid = models.CharField( + default=uuid.uuid4, max_length=36, unique=True, primary_key=True) + # index in favor of getRecentEng, getStarredEng + engagement = models.OneToOneField( + Engagement, null=False, blank=False, default=-1, db_index=True) + deployment_target = models.ForeignKey( + DeploymentTarget, on_delete=models.SET_NULL, null=True, blank=True) + ecomp_release = models.ForeignKey(ECOMPRelease, null=True, blank=False) + deployment_target_sites = models.ManyToManyField( + DeploymentTargetSite, default=None, blank=True, related_name='DeployTarget_sites') + is_service_provider_internal = models.BooleanField(default=False) + vendor = models.ForeignKey(Vendor, on_delete=models.PROTECT) + git_repo_url = models.CharField(max_length=512, blank=False, default=-1) + target_lab_entry_date = models.DateField( + 'target_lab_entry_date', null=False) + + def jenkins_job_name(self): + if not self.engagement.engagement_manual_id: + raise ValueError( + "engagement_manual_id (%s) is not valid for jenkins job name" % self.engagement.engagement_manual_id) + return "{self.name}_{self.engagement.engagement_manual_id}".format(self=self) + + def __str__(self): + return self.name + + class Meta: + db_table = "ice_vf" + + +class VFC(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, unique=True, primary_key=True) + vf = models.ForeignKey(VF, on_delete=models.PROTECT, db_index=True) + # in favor of dashboard search by keyword + name = models.CharField(max_length=100, db_index=True) + external_ref_id = models.CharField(max_length=20, default='') + ice_mandated = models.BooleanField(default=False) + company = models.ForeignKey(Vendor, on_delete=SET_NULL, null=True) + create_time = models.DateTimeField('creation time', default=timezone.now) + creator = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, null=True, blank=True, related_name='Vfc_creator') + + def __str__(self): + return self.name + + class Meta: + db_table = "ice_vfc" + + +class RecentEngagement(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=64, primary_key=True) + vf = models.ForeignKey(VF, on_delete=models.CASCADE) + user_uuid = models.CharField(max_length=64) + action_type = models.CharField( + max_length=36, choices=RecentEngagementActionType.choices()) + last_update = models.DateTimeField('update time', default=timezone.now) + + def __str__(self): + return " uuid: " + str(self.uuid) + + class Meta: + db_table = "ice_recent_engagement" + +# _________________________ C H E C K - L I S T __________________________ + + +class ChecklistTemplate(models.Model): # Reference Table + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + name = models.CharField('template name', max_length=255) + category = models.CharField(max_length=36, choices=CheckListCategory.choices( + ), default=CheckListCategory.overall.name) # @UndefinedVariable + version = models.IntegerField('template version') + create_time = models.DateTimeField('creation time', default=timezone.now) + update_time = models.DateTimeField( + 'last update time', null=True, blank=True) + + def __str__(self): + return self.name + ' ' + self.category + + class Meta: + db_table = "ice_checklist_template" + + +class ChecklistSection(models.Model): # Reference Table + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + name = models.CharField('section name', max_length=255) + weight = models.FloatField('checklist weight') + description = models.TextField('section description') + validation_instructions = models.TextField( + 'section validation instructions') + create_time = models.DateTimeField('creation time', default=timezone.now) + update_time = models.DateTimeField( + 'last update time', null=True, blank=True) + parent_section = models.ForeignKey("self", null=True, blank=True) + template = models.ForeignKey( + ChecklistTemplate, on_delete=models.PROTECT, null=False, blank=False) + + def __str__(self): + return self.name + ' ' + self.description + + class Meta: + db_table = "ice_checklist_section" + + +class ChecklistLineItem(models.Model): # Reference Table + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + name = models.CharField('line name', max_length=255) + weight = models.FloatField('line weight') + description = models.TextField('line description') + line_type = models.CharField(max_length=36, choices=CheckListLineType.choices( + ), default=CheckListLineType.auto.name) # @UndefinedVariable + validation_instructions = models.TextField('line validation instructions') + create_time = models.DateTimeField('creation time', default=timezone.now) + update_time = models.DateTimeField( + 'last update time', null=True, blank=True) + template = models.ForeignKey( + ChecklistTemplate, on_delete=models.CASCADE, null=False, blank=False) + section = models.ForeignKey( + ChecklistSection, on_delete=models.CASCADE, null=False, blank=False) + + def save(self, *args, **kwargs): + if (self.template != self.section.template != None): + raise ValueError("ChecklistLineItem can't be saved/updated since the template " + + self.template.name + " is not equal to its section's template " + self.section.template.name) + super(ChecklistLineItem, self).save(*args, **kwargs) + + def __str__(self): + return self.name + ' ' + self.description + + class Meta: + db_table = "ice_checklist_line_item" + + +class Checklist(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + name = models.CharField('checklist name', max_length=255) + state = models.CharField(max_length=36, choices=CheckListState.choices( + ), default=CheckListState.pending.name) # @UndefinedVariable + # On each validation cycle this counter is increased + validation_cycle = models.IntegerField('validation cycle') + weight = models.FloatField('checklist weight', default=0) + associated_files = models.TextField('list of files from gitlab') + create_time = models.DateTimeField('creation time', default=timezone.now) + update_time = models.DateTimeField( + 'last update time', null=True, blank=True) + # index in favor of get StarredEngagements (especially for admin and EL) + engagement = models.ForeignKey( + Engagement, on_delete=models.CASCADE, db_index=True) + template = models.ForeignKey(ChecklistTemplate, on_delete=models.PROTECT) + # The EL that opened the modal. + creator = models.ForeignKey( + IceUserProfile, on_delete=models.CASCADE, related_name='checklist_creator') + # The user who currently validates the checklist + owner = models.ForeignKey( + IceUserProfile, on_delete=models.CASCADE, related_name='checklist_owner') + + def __str__(self): + return self.name + ' ' + self.state + + class Meta: + db_table = "ice_checklist" + + +class NextStep(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + create_time = models.DateTimeField('creation time', default=timezone.now) + creator = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, related_name="NextStep_creator") + last_update_time = models.DateTimeField( + 'last update time', default=timezone.now) + last_updater = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, null=True, related_name="NextStep_last_updater") + # Can be: Modified, Added, Completed, Denied + last_update_type = models.CharField(max_length=15, default='Added') + position = models.IntegerField() + description = models.TextField() + # Can be: Incomplete, Completed + state = models.CharField(max_length=15, choices=NextStepState.choices()) + # Can be: Intake, Active, Validated, Completed. This field is used to + # correlate between the engagement stage to the next step stage in favor + # of UI. + engagement_stage = models.CharField(max_length=15) + engagement = models.ForeignKey( + Engagement, on_delete=models.PROTECT, null=True, blank=True) + owner = models.ForeignKey( + IceUserProfile, on_delete=models.PROTECT, null=True, blank=True) + next_step_type = models.CharField(max_length=36, choices=NextStepType.choices( + ), default=NextStepType.user_defined.name) # @UndefinedVariable + files = models.TextField('list of files', null=True) + assignees = models.ManyToManyField( + IceUserProfile, related_name='assignees') + due_date = models.DateField('due_date', null=True) + + def __str__(self): + return self.engagement_stage + ' ' + self.state + ' ' + self.description + + class Meta: + db_table = "ice_next_step" + verbose_name_plural = 'Next steps' + # index in favor of nextstep_service.get_next_steps + index_together = ["engagement_stage", "owner"] + + +class ChecklistDecision(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + review_value = models.CharField( + max_length=36, choices=CheckListDecisionValue.choices()) # @UndefinedVariable + peer_review_value = models.CharField( + max_length=36, choices=CheckListDecisionValue.choices()) # @UndefinedVariable + create_time = models.DateTimeField('creation time', default=timezone.now) + update_time = models.DateTimeField( + 'last update time', null=True, blank=True) + checklist = models.ForeignKey(Checklist, on_delete=models.CASCADE) + template = models.ForeignKey(ChecklistTemplate, on_delete=models.CASCADE) + lineitem = models.ForeignKey(ChecklistLineItem, on_delete=models.CASCADE) + + def save(self, *args, **kwargs): + if (self.template != self.checklist.template != None): + raise ValueError("ChecklistDecision can't be saved/updated since the template " + + self.template.name + " is not equal to its checklist's template " + self.checklist.template.name) + if (self.template != self.lineitem.section.template != None): + raise ValueError("ChecklistDecision can't be saved/updated since the template " + self.template.name + + " is not equal to its lineitem/section's template " + self.lineitem.section.template) + if (self.checklist.template != self.lineitem.section.template != None): + raise ValueError("ChecklistDecision can't be saved/updated since its checklist's template " + + self.checklist.template + " is not equal to its lineitem/section's template " + self.lineitem.section.template) + super(ChecklistDecision, self).save(*args, **kwargs) + + def __str__(self): + return 'decision:' + self.uuid + ' ' + self.template.name + ' ' + self.review_value + ' ' + self.peer_review_value + + class Meta: + db_table = "ice_checklist_decision" + + +class ChecklistAuditLog(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + category = models.CharField(max_length=255) + description = models.TextField() + create_time = models.DateTimeField('creation time', default=timezone.now) + update_time = models.DateTimeField( + 'last update time', null=True, blank=True) + creator = models.ForeignKey(IceUserProfile) + # should be None if decisions is populated + checklist = models.ForeignKey( + Checklist, on_delete=models.CASCADE, null=True, blank=True) + # should be None if checklist is populated + decision = models.ForeignKey( + ChecklistDecision, on_delete=models.CASCADE, null=True, blank=True) + + def save(self, *args, **kwargs): + if (self.checklist != None and self.decision != None): + raise ValueError( + "ChecklistAuditLog can't be attached to both checklist and decision. Please remove one of them and retry the operation") + super(ChecklistAuditLog, self).save(*args, **kwargs) + + def __str__(self): + return self.category + ' ' + self.description + + class Meta: + db_table = "ice_checklist_audit_log" + + +class Invitation(models.Model): + uuid = models.CharField( + default=uuid.uuid4, max_length=36, primary_key=True) + engagement_uuid = models.CharField( + max_length=64, null=False, blank=False, db_index=True) + invited_by_user_uuid = models.CharField( + max_length=64, null=False, blank=False, db_index=True) + email = models.CharField(max_length=255, null=False, blank=False) + invitation_token = models.CharField( + max_length=1024, null=False, blank=False, db_index=True) # index in favor of signup + accepted = models.BooleanField(default=False) + create_time = models.DateTimeField( + 'invitation creation time', default=timezone.now) + + def __str__(self): + return "Invite from " + self.invited_by_user_uuid + " to " + self.email + " for joining engagement " + self.engagement_uuid + + class Meta: + db_table = "ice_invitation" + unique_together = (("engagement_uuid", "email"),) diff --git a/django/engagementmanager/nextsteps.py b/django/engagementmanager/nextsteps.py new file mode 100755 index 0000000..3fee019 --- /dev/null +++ b/django/engagementmanager/nextsteps.py @@ -0,0 +1,114 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.utils import timezone +from django.utils.timezone import timedelta +from engagementmanager.models import NextStep +from engagementmanager.service.logging_service import LoggingServiceFactory +from engagementmanager.utils.constants import Constants, NextStepType + + +logger = LoggingServiceFactory.get_logger() + +default_next_steps = [ + + + { + 'position': 2, + 'stage': 'Intake', + 'text': 'Please work with your Engagement Lead (EL) to complete the necessary trial agreements.', + 'condition': lambda x, y: True, + 'type': NextStepType.trial_agreements.name # @UndefinedVariable + }, + { + 'position': 3, + 'stage': 'Intake', + 'text': 'Please add your ' + Constants.service_provider_company_name + ' sponsor or vendor contact information.', + 'condition': lambda user, eng: False if (eng.contact_user) else True, + 'type': NextStepType.add_contact_person.name # @UndefinedVariable + }, + { + 'position': 1, + 'stage': 'Active', + 'text': 'Please submit the first version of the VF package. If you have any problems or questions, please contact your Engagement Lead (EL)', + 'condition': lambda x, y: True, + 'type': NextStepType.submit_vf_package.name # @UndefinedVariable + }, + { + 'position': 1, + 'stage': 'Validated', + 'text': 'Please schedule a time with your Engagement Lead (EL) to complete the handoff.', + 'condition': lambda x, y: True, + 'type': NextStepType.el_handoff.name # @UndefinedVariable + } +] + + +def create_default_next_steps_for_user(user, el_user): + """ + This method is for personal default next step only since it has an owner + """ + def cond(user): return False if (user.ssh_public_key and user.ssh_public_key != '') else True + if cond(user): + desc = "Please add your SSH key to be able to contribute." + nextstep = NextStep.objects.create(creator=el_user, last_updater=el_user, position=1, description=desc, last_update_type='Added', state='Incomplete', + engagement_stage='Intake', engagement=None, owner=user, next_step_type=NextStepType.set_ssh.name, due_date=timezone.now() + timedelta(days=1)) # @UndefinedVariable + nextstep.assignees.add(user) + nextstep.save() + + +def create_default_next_steps(user, engagement, el_user): + """ + This method is for non-personal default next step only since it doesn't have an owner + """ + for step in default_next_steps: + cond = step['condition'] + desc = step['text'] + ns_type = step['type'] + if cond(user, engagement): + if (user.company == Constants.service_provider_company): + desc = desc.replace('$Contact', 'Vendor Contact') + else: + desc = desc.replace('$Contact', Constants.service_provider_company_name + ' Sponsor Contact') + logger.debug('Creating default next step : ' + desc) + nextstep = NextStep.objects.create(creator=el_user, last_updater=el_user, position=step['position'], description=desc, state='Incomplete', engagement_stage=step[ + 'stage'], engagement=engagement, next_step_type=ns_type, due_date=timezone.now() + timedelta(days=1)) + nextstep.assignees.add(el_user) + nextstep.save() + else: + logger.debug('Skipping creation of default next step : ' + desc) diff --git a/django/engagementmanager/notifications.py b/django/engagementmanager/notifications.py new file mode 100755 index 0000000..59f2e1f --- /dev/null +++ b/django/engagementmanager/notifications.py @@ -0,0 +1,71 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.models import Notification, IceUserProfile +from engagementmanager.serializers import ThinNotificationModelSerializer +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def num_of_notifications_for_user(user_uuid): + user = IceUserProfile.objects.get(uuid=user_uuid) + amountOfnotificationForUser = Notification.objects.filter(user=user, is_read=False).filter().count() + return amountOfnotificationForUser + + +def pull_recent_notifications(user_uuid, offset, limit): + ModifiedNotificationsSet = [] + logger.debug("Pulling unread notifications from DB") + user = IceUserProfile.objects.get(uuid=user_uuid) + notificationsList = Notification.objects.filter(user=user).order_by('is_read', '-activity__create_time')[int(offset):int(offset) + int(limit)] + num_of_objects = Notification.objects.filter(user=user).count() + for notif in notificationsList: + serializedNotification = ThinNotificationModelSerializer(notif).data + ModifiedNotificationsSet.append(serializedNotification) + notif.is_read = True + notif.save() + return ModifiedNotificationsSet, num_of_objects + + +def reset_num_of_notifications_for_user(user_uuid): + user = IceUserProfile.objects.get(uuid=user_uuid) + notificationForUser = Notification.objects.filter(user=user, is_read=False) + for notif in notificationForUser: + notif.is_read = True + notif.save() diff --git a/django/engagementmanager/rest/__init__.py b/django/engagementmanager/rest/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/rest/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/rest/activation.py b/django/engagementmanager/rest/activation.py new file mode 100755 index 0000000..3499b95 --- /dev/null +++ b/django/engagementmanager/rest/activation.py @@ -0,0 +1,123 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.conf import settings +from django.template.loader import get_template +from django.utils import timezone +from itsdangerous import SignatureExpired +from rest_framework.permissions import IsAuthenticatedOrReadOnly +from rest_framework.response import Response +from engagementmanager import mail +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import IceUserProfile +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.utils.constants import Constants +from engagementmanager.utils.vvp_exceptions import VvpObjectNotAvailable, VvpGeneralException, VvpBadRequest +from engagementmanager.views_helper import generateActivationLink, getFirstEngByUser +from engagementmanager.vm_integration import vm_client +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +@classDecorator([logFuncEntry]) +class ResendActivationMail(VvpApiView): + permission_classes = (IsAuthenticatedOrReadOnly,) + + def get(self, request, user_uuid, format=None): + ice_user_obj = IceUserProfile.objects.get(uuid=user_uuid) + + data = {'activation_link': generateActivationLink(ice_user_obj.user.activation_token, ice_user_obj), + 'full_name': ice_user_obj.full_name} + + # updating the activation time + ice_user_obj.user.activation_token_create_time = timezone.now() + + ice_user_obj.save() + self.logger.debug("Activation Link: " + data['activation_link']) + + body = get_template("{activate_template_dir}activate_mail_body.html".format( + activate_template_dir=Constants.activate_template_dir)) + subject = get_template("{activate_template_dir}activate_mail_subject.html".format( + activate_template_dir=Constants.activate_template_dir)) + mail.sendMail(ice_user_obj.email, data, body, subject) + + return Response() + + +@classDecorator([logFuncEntry]) +class ActivateUser(VvpApiView): + permission_classes = (IsAuthenticatedOrReadOnly,) + + def get(self, request, format=None, **kwargs): + user_profile = IceUserProfile.objects.get(uuid=kwargs['uu_id']) + user = user_profile.user + if user is None: + raise VvpObjectNotAvailable( + "User's retrieved in the activation API doesn't exist.") + + if user.is_active: + raise VvpGeneralException( + "User's retrieved in the activation API is active.") + + if user.activation_token != kwargs['token']: + raise VvpBadRequest( + "User's activation token is not equal to the token in the activation path param.") + + created = user.activation_token_create_time + current = timezone.now() + if created.year == current.year and created.month == current.month and (created.day == current.day or + created.day == current.day - 1): + delta = current - created + if abs(delta).total_seconds() / 3600.0 <= settings.TOKEN_EXPIRATION_IN_HOURS: + user.is_active = True + user.save() + self.logger.debug( + "User " + user_profile.full_name + " is activated successfully, redirecting to Login") + user = IceUserProfile.objects.get(email=user.email) + eng = getFirstEngByUser(user) + result = {'activation_success': True, } + if eng is not None: + result['engagement_uuid'] = str(eng.uuid) + vm_client.send_create_user_in_rgwa_event(user) + return Response(result) + else: + raise SignatureExpired("User's activation token expired.") + + return Response({'activation_success': False, }) diff --git a/django/engagementmanager/rest/activity.py b/django/engagementmanager/rest/activity.py new file mode 100755 index 0000000..47b4cc7 --- /dev/null +++ b/django/engagementmanager/rest/activity.py @@ -0,0 +1,65 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.conf import settings +from rest_framework.response import Response + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import Engagement +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import ActivityModelSerializer +from engagementmanager.service.activities_service import ActivitiesSvc +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.utils.request_data_mgr import request_data_mgr + + +@classDecorator([logFuncEntry]) +class PullActivities(VvpApiView): + def __init__(self): + self.activities_service = ActivitiesSvc() + + @auth(Permissions.pull_activities) + def get(self, request, eng_uuid, num=None): + if not num: + num = settings.NUMBER_OF_POLLED_ACTIVITIES + eng = Engagement.objects.get(uuid=request_data_mgr.get_eng_uuid()) + activities = self.activities_service.pull_recent_activities(eng, recent_activities_limit=num) + serializer = ActivityModelSerializer(activities, many=True) + return Response(serializer.data) diff --git a/django/engagementmanager/rest/checklist.py b/django/engagementmanager/rest/checklist.py new file mode 100755 index 0000000..200dcaa --- /dev/null +++ b/django/engagementmanager/rest/checklist.py @@ -0,0 +1,139 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from rest_framework.response import Response +from rest_framework.status import HTTP_400_BAD_REQUEST,\ + HTTP_500_INTERNAL_SERVER_ERROR + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.checklist_service import CheckListSvc +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.utils.validator import Validator + + +@classDecorator([logFuncEntry]) +class NewCheckList(VvpApiView): + + @auth(Permissions.view_checklist) + def get(self, request, eng_uuid): + + user = request_data_mgr.get_user() + eng_uuid = request_data_mgr.get_eng_uuid() + data = CheckListSvc().getDataForCreateNewChecklist(user, eng_uuid) + if not data: + msg = "Create New checklist is not ready yet" + return Response(msg, status=HTTP_500_INTERNAL_SERVER_ERROR) + return Response(data) + + @auth(Permissions.is_el_of_eng) + def post(self, request, eng_uuid): + data = request.data + + if ('checkListName' not in data or not data['checkListName'] or + 'checkListTemplateUuid' not in data or not data['checkListTemplateUuid'] or + 'checkListAssociatedFiles' not in data): + msg = "One of the CheckList's input parameters is missing" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + + if not Validator.validateCheckListName(data['checkListName']): + msg = "Invalid characters in check list name." + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + + data = CheckListSvc().createOrUpdateChecklist( + data['checkListName'], data['checkListTemplateUuid'], data['checkListAssociatedFiles'], None) + + return Response(data) + + +@classDecorator([logFuncEntry]) +class ExistingCheckList(VvpApiView): + + @auth(Permissions.view_checklist) + def get(self, request, checklistUuid): + user = request_data_mgr.get_user() + checklist_uuid = request_data_mgr.get_cl_uuid() + data = CheckListSvc().getChecklist(user, checklist_uuid) + return Response(data) + + @auth(Permissions.is_el_of_eng) + def delete(self, request): + CheckListSvc().deleteChecklist(request_data_mgr.get_cl_uuid()) + return Response() + + @auth(Permissions.is_el_of_eng) + def put(self, request, checklistUuid): + data = request.data + if ('checklistUuid' not in data or not data['checklistUuid'] or + 'checkListName' not in data or not data['checkListName'] or + 'checkListTemplateUuid' not in data or not data['checkListTemplateUuid'] or + 'checkListAssociatedFiles' not in data): + msg = "One of the CheckList's input parameters is missing" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + if not Validator.validateCheckListName(data['checkListName']): + msg = "Invalid characters in check list name." + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + + data = CheckListSvc().createOrUpdateChecklist( + data['checkListName'], data['checkListTemplateUuid'], data['checkListAssociatedFiles'], data['checklistUuid']) + + return Response(data) + + +@classDecorator([logFuncEntry]) +class CheckListTemplates(VvpApiView): + + @auth(Permissions.view_checklist_template) + def get(self, request, templateUuid=None): + data = CheckListSvc().getChecklistTemplates(templateUuid) + return Response(data) + + @auth(Permissions.edit_checklist_template) + def put(self, request): + data = request.data + CheckListSvc().editChecklistTemplate(data) + return Response() diff --git a/django/engagementmanager/rest/checklist_audit_log.py b/django/engagementmanager/rest/checklist_audit_log.py new file mode 100755 index 0000000..4b86a33 --- /dev/null +++ b/django/engagementmanager/rest/checklist_audit_log.py @@ -0,0 +1,103 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from rest_framework.response import Response + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import ChecklistDecision, Checklist +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.checklist_audit_log_service import getAuditLogsWithChecklist, \ + addAuditLogToChecklist, getAuditLogsWithDecision, addAuditLogToDecision +from engagementmanager.utils.request_data_mgr import request_data_mgr + + +@classDecorator([logFuncEntry]) +class ChecklistAuditLog(VvpApiView): + + @auth(Permissions.view_checklist) + def get(self, request, checklistUuid): + user = request_data_mgr.get_user() + checklistUuid = request_data_mgr.get_cl_uuid()() + data = getAuditLogsWithChecklist(checklistUuid, user) + return Response(data) + + @auth(Permissions.create_checklist_audit_log) + def post(self, request, checklistUuid): + data = request.data + user = request_data_mgr.get_user() + checklistUuid = request_data_mgr.get_cl_uuid() + + if ('description' not in data or not data['description']): + msg = "description for the audit log is not provided in the request's body" + self.logger.error(msg) + raise KeyError(msg) + description = data['description'] + checklist = Checklist.objects.get(uuid=checklistUuid) + data = addAuditLogToChecklist(checklist, description, user) + return Response(data) + + +@classDecorator([logFuncEntry]) +class DecisionAuditLog(VvpApiView): + + @auth(Permissions.view_checklist) + def get(self, request, decision_uuid): + user = request_data_mgr.get_user() + decisionUuid = decision_uuid + data = getAuditLogsWithDecision(decisionUuid, user) + + return Response(data) + + @auth(Permissions.create_checklist_decision) + def post(self, request, decision_uuid): + data = request.data + user = request_data_mgr.get_user() + decisionUuid = decision_uuid + if ('description' not in data or not data['description']): + msg = "value for decision is not provided in the request's body" + self.logger.error(msg) + raise KeyError(msg) + description = data['description'] + decision = ChecklistDecision.objects.get(uuid=decisionUuid) + auditData = addAuditLogToDecision(decision, description, user) + return Response(auditData) diff --git a/django/engagementmanager/rest/checklist_decision.py b/django/engagementmanager/rest/checklist_decision.py new file mode 100755 index 0000000..a0cfe01 --- /dev/null +++ b/django/engagementmanager/rest/checklist_decision.py @@ -0,0 +1,76 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from rest_framework.response import Response +from rest_framework.status import HTTP_400_BAD_REQUEST + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.checklist_decision_service import setDecision, getDecision +from engagementmanager.utils.request_data_mgr import request_data_mgr + + +@classDecorator([logFuncEntry]) +class ClDecision(VvpApiView): + + @auth(Permissions.view_checklist) + def get(self, request, decision_uuid): + user = request_data_mgr.get_user() + decisionUuid = decision_uuid + data = getDecision(decisionUuid, user) + return Response(data) + + @auth(Permissions.update_checklist_decision) + def put(self, request, decision_uuid): + data = request.data + + user = request_data_mgr.get_user() + decisionUuid = decision_uuid + if 'value' not in data or not data['value']: + msg = "value for decision is not provided in the request's body" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + value = data['value'] + msg = setDecision(decisionUuid, user, value) + msg = json.dumps(msg, ensure_ascii=False) + return Response(msg) diff --git a/django/engagementmanager/rest/checklist_set_state.py b/django/engagementmanager/rest/checklist_set_state.py new file mode 100755 index 0000000..e9c6eb3 --- /dev/null +++ b/django/engagementmanager/rest/checklist_set_state.py @@ -0,0 +1,67 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from rest_framework.response import Response + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import SuperThinChecklistModelSerializer +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.checklist_state_service import set_state +from engagementmanager.utils.request_data_mgr import request_data_mgr + + +@classDecorator([logFuncEntry]) +class ChecklistState(VvpApiView): + + @auth(Permissions.update_checklist_state) + def put(self, request, checklistUuid): + data = request.data + decline = data['decline'] + if decline == "True": + checklist = set_state(True, request_data_mgr.get_cl_uuid(), + isMoveToAutomation=False, description=data['description']) + else: + checklist = set_state(False, request_data_mgr.get_cl_uuid(), description=data['description']) + + cldata = json.dumps(SuperThinChecklistModelSerializer(checklist).data, ensure_ascii=False) + return Response(cldata) diff --git a/django/engagementmanager/rest/cms/__init__.py b/django/engagementmanager/rest/cms/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/rest/cms/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/rest/cms/pages.py b/django/engagementmanager/rest/cms/pages.py new file mode 100755 index 0000000..efe0b4e --- /dev/null +++ b/django/engagementmanager/rest/cms/pages.py @@ -0,0 +1,80 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.response import Response + +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.cms.pages_service import CMSPagesService + + +@classDecorator([logFuncEntry]) +class Pages(VvpApiView): + cms_service = CMSPagesService() + + def get(self, request, format=None, **kwargs): + titleParam = request.GET.get('title', "") + + pages = self.cms_service.getPages(titleParam) + return Response(pages) + + +@classDecorator([logFuncEntry]) +class PageById(VvpApiView): + cms_service = CMSPagesService() + + def get(self, request, format=None, **kwargs): + idParam = kwargs['id'] + + pages = self.cms_service.getPage(idParam) + return Response(pages) + + +@classDecorator([logFuncEntry]) +class PageSearch(VvpApiView): + cms_service = CMSPagesService() + + def get(self, request): + keyword = request.GET.get('keyword', "") + result = [] + + if keyword is not None and keyword != "": + result = self.cms_service.searchPages(keyword) + + return Response(result) diff --git a/django/engagementmanager/rest/cms/posts.py b/django/engagementmanager/rest/cms/posts.py new file mode 100755 index 0000000..17e33fb --- /dev/null +++ b/django/engagementmanager/rest/cms/posts.py @@ -0,0 +1,57 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.response import Response + +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.cms.posts_service import CMSPostsService + + +@classDecorator([logFuncEntry]) +class Posts(VvpApiView): + + def get(self, request, format=None, **kwargs): + categoryParam = request.GET.get('category', "") + limitParam = request.GET.get('limit', 5) + offsetParam = request.GET.get('offset', 0) + fromLastDaysParam = request.GET.get('fromLastDays', None) + + posts = CMSPostsService().getPosts(offsetParam, limitParam, fromLastDaysParam, categoryParam) + return Response(posts) diff --git a/django/engagementmanager/rest/csrf_exempt_session_authentication.py b/django/engagementmanager/rest/csrf_exempt_session_authentication.py new file mode 100755 index 0000000..89a6243 --- /dev/null +++ b/django/engagementmanager/rest/csrf_exempt_session_authentication.py @@ -0,0 +1,47 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.authentication import SessionAuthentication + + +class CsrfExemptSessionAuthentication(SessionAuthentication): + + def enforce_csrf(self, request): + # To not perform the csrf check previously happening + # (http://stackoverflow.com/questions/30871033/django-rest-framework-remove-csrf) + return diff --git a/django/engagementmanager/rest/data_loader.py b/django/engagementmanager/rest/data_loader.py new file mode 100755 index 0000000..11e8dfc --- /dev/null +++ b/django/engagementmanager/rest/data_loader.py @@ -0,0 +1,82 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from uuid import uuid4 + +from django.utils import timezone +from rest_framework.response import Response + +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import IceUserProfile, Vendor, Role, CustomUser +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.utils.constants import Constants +from engagementmanager.utils.validator import logEncoding +from engagementmanager.views_helper import createUserTemplate + + +@classDecorator([logFuncEntry]) +class EngLeadsDataLoader(VvpApiView): + + def get(self, request): + data = request.data + service_provider_company = Vendor.objects.get(name=Constants.service_provider_company_name) + el_role = Role.objects.get(name="el") + for el in data: + user_object = CustomUser.objects.create_user( + username=el['full_name'], email=el['full_name'], password=el['password'], is_active=False, activation_token=uuid4(), activation_token_create_time=timezone.now()) + data = createUserTemplate(service_provider_company, el['full_name'], el_role, '', True, None, True, user_object) + el_user, is_profile_created = IceUserProfile.objects.update_or_create( + email=user_object.email, defaults=data) + self.logger.info("User: " + el_user.full_name + + " was created successfully during bulk_load_engagement_leads function") + self.logger.info("All users were created successfully during bulk_load_engagement_leads function") + return Response() + + +@classDecorator([logFuncEntry]) +class CompaniesDataLoader(VvpApiView): + + def get(self, request): + data = request.data + for vendor in data: + Vendor.objects.get_or_create(name=vendor['name'], defaults={'public': True}) + self.logger.info('Company found or created during bulk load vendors: ' + logEncoding(vendor)) + self.logger.info("All companies were created successfully during bulk_load_companies function") + return Response() diff --git a/django/engagementmanager/rest/deployment_target.py b/django/engagementmanager/rest/deployment_target.py new file mode 100755 index 0000000..c52d9b9 --- /dev/null +++ b/django/engagementmanager/rest/deployment_target.py @@ -0,0 +1,69 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.status import HTTP_400_BAD_REQUEST + +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import DeploymentTarget +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import DeploymentTargetModelSerializer +from engagementmanager.service.deploment_target_service import update_deployment_target + + +@classDecorator([logFuncEntry]) +class DeploymentTargetRESTMethods(VvpApiView): + permission_classes = (IsAuthenticated,) + + def put(self, request, engagement_uuid, dt_uuid): + msg = "OK" + if engagement_uuid and dt_uuid: + update_deployment_target(engagement_uuid, dt_uuid) + return Response(msg) + else: + msg = "DTarget PUT Request failed, engagement_uuid wasn't found in kwargs or its content is empty, therefore cannot filter by it to find the required VF" + self.logger.error(msg) + msg = "Action failed." + return Response(msg, status=HTTP_400_BAD_REQUEST) + + def get(self, request): + deployment_targets = DeploymentTarget.objects.filter(ui_visibility=True).order_by('weight') + serializer = DeploymentTargetModelSerializer(deployment_targets, many=True) + return Response(serializer.data) diff --git a/django/engagementmanager/rest/deployment_target_site.py b/django/engagementmanager/rest/deployment_target_site.py new file mode 100755 index 0000000..32ff5a4 --- /dev/null +++ b/django/engagementmanager/rest/deployment_target_site.py @@ -0,0 +1,103 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.response import Response +from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_204_NO_CONTENT + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import VF, DeploymentTargetSite +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import ThinDeploymentTargetSiteModelSerializer +from engagementmanager.service.authorization_service import Permissions + + +@classDecorator([logFuncEntry]) +class DTSites(VvpApiView): + + @auth(Permissions.get_deployment_target_site) + def get(self, request, vf_uuid=None): + if vf_uuid: + vf = VF.objects.get(uuid=vf_uuid) + dtsites = vf.deployment_target_sites + serializer = ThinDeploymentTargetSiteModelSerializer(dtsites, many=True) + return Response(serializer.data) + else: + dtsites = DeploymentTargetSite.objects.all() + serializer = ThinDeploymentTargetSiteModelSerializer(dtsites, many=True) + return Response(serializer.data) + + """ + expecting: VF object uuid, DeploymentTargetSite uuid + result: addition of the DeploymentTargetSite object with dtsite_uuid to the VF's deployment_target_sites + """ + @auth(Permissions.add_deployment_target_site) + def post(self, request): + msg = "" + data = request.data + name = data['name'] + dtsite = None + + try: + dtsite = DeploymentTargetSite.objects.get(name=name) + msg = "DTSite was already existed, hence would next be added to the VF's sites list" + except DeploymentTargetSite.DoesNotExist: + dtsite = DeploymentTargetSite.objects.create(name=name) + dtsite.save() + vf = VF.objects.get(uuid=data['vf_uuid']) + vf.deployment_target_sites.add(dtsite) + vf.save() + return Response(msg) + + @auth(Permissions.delete_deployment_target_site) + def delete(self, request, vf_uuid, dts_uuid): + msg = "OK" + dtsite = None + vf = None + + if vf_uuid and dts_uuid: + dtsite = DeploymentTargetSite.objects.get(uuid=dts_uuid) + vf = VF.objects.get(uuid=vf_uuid) + vf.deployment_target_sites.remove(dtsite) + vf.save() + return Response(msg, status=HTTP_204_NO_CONTENT) + else: + msg = "dtsite uuid or vf uuid, wasn't provided" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) diff --git a/django/engagementmanager/rest/ecomp.py b/django/engagementmanager/rest/ecomp.py new file mode 100755 index 0000000..a2585ac --- /dev/null +++ b/django/engagementmanager/rest/ecomp.py @@ -0,0 +1,69 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_202_ACCEPTED + +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import ECOMPRelease +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import ECOMPReleaseModelSerializer +from engagementmanager.service.ecomp_service import update_ECOMP + + +@classDecorator([logFuncEntry]) +class ECOMPReleaseRESTMethods(VvpApiView): + permission_classes = (IsAuthenticated,) + + def put(self, request, engagement_uuid, ecomp_uuid): + msg = "OK" + if engagement_uuid and ecomp_uuid: + update_ECOMP(engagement_uuid, ecomp_uuid) + return Response(msg) + else: + msg = "ECOMPRelease PUT Request failed, engagement_uuid wasn't found in kwargs or its content is empty, therefore cannot filter by it to find the required VF" + self.logger.error(msg) + msg = "Action failed." + return Response(msg, status=HTTP_400_BAD_REQUEST) + + def get(self, request): + ecomp_releases = ECOMPRelease.objects.filter(ui_visibility=True).order_by('weight') + serializer = ECOMPReleaseModelSerializer(ecomp_releases, many=True) + return Response(serializer.data) diff --git a/django/engagementmanager/rest/engagement.py b/django/engagementmanager/rest/engagement.py new file mode 100755 index 0000000..89e74fe --- /dev/null +++ b/django/engagementmanager/rest/engagement.py @@ -0,0 +1,665 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.db.models.expressions import F +from django.db.models.query_utils import Q +from django.http.response import HttpResponse +from django.utils.dateparse import parse_date +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.git.git_manager import GitManager +from engagementmanager.models import Engagement, VF, VFC, Checklist, \ + EngagementStatus +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import VFModelSerializer, \ + EngagementStatusModelSerializer +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service import engagement_service as eng_svc +from engagementmanager.utils.constants import Roles, RecentEngagementActionType, \ + CheckListState, EngagementStage +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.utils.validator import logEncoding +from rest_framework.response import Response +from rest_framework.status import HTTP_500_INTERNAL_SERVER_ERROR, \ + HTTP_400_BAD_REQUEST, HTTP_200_OK, HTTP_204_NO_CONTENT, \ + HTTP_401_UNAUTHORIZED, HTTP_202_ACCEPTED + + +@classDecorator([logFuncEntry]) +class ExpandedEngByUser(VvpApiView): + + def post(self, request): + data = request.data + if ('stage' not in data or not data['stage'] + or 'keyword' not in data + or 'offset' not in data or int(data['offset']) < 0 + or 'limit' not in data or not data['limit'] or (data['limit'] < 1)): + msg = "GetExpandedEngByUser - get request: one of the parameters is missing or invalid." + self.logger.error(msg) + msg = "Action was failed due to bad request." + return Response(msg, status=HTTP_400_BAD_REQUEST) + user = request_data_mgr.get_user() + data = eng_svc.get_dashboard_expanded_engs( + data['stage'], data['keyword'], data['offset'], data['limit'], user) + return Response(data) + + +@classDecorator([logFuncEntry]) +class ExportEngagements(VvpApiView): + + @auth(Permissions.export_engagments) + def get(self, request): + from openpyxl import Workbook + from openpyxl.writer.write_only import WriteOnlyCell + from openpyxl.styles import Font + # import csv + from django.utils.encoding import smart_str + + user = request_data_mgr.get_user() + stageParam = request.GET['stage'] + keywordParam = request.GET['keyword'] + + # data, status = eng_svc.get_dashboard_expanded_engs(stageParam, keywordParam, 0, sys.maxint, user) + vfs, deployment_targets = eng_svc.get_expanded_engs_for_export( + stageParam, keywordParam, user) + + workbook = Workbook(write_only=True) + # Create 'Validation Details' sheet and fill it up with required data: + validationWorkSheet = workbook.create_sheet() + validationWorkSheet.title = 'Validation Details' + headlines = [WriteOnlyCell(validationWorkSheet, value=u"EId"), + WriteOnlyCell(validationWorkSheet, value=u"Engagement"), + WriteOnlyCell(validationWorkSheet, value=u"Reviewer"), + WriteOnlyCell( + validationWorkSheet, value=u"Peer reviewer"), + WriteOnlyCell(validationWorkSheet, value=u"VFC"), + WriteOnlyCell(validationWorkSheet, value=u"VFC #"), + WriteOnlyCell(validationWorkSheet, value=u"Started"), + WriteOnlyCell(validationWorkSheet, value=u"Vendor"), + WriteOnlyCell(validationWorkSheet, value=u"AIC Version"), + WriteOnlyCell( + validationWorkSheet, value=u"ECOMP Release"), + WriteOnlyCell(validationWorkSheet, value=u"Validate"), + WriteOnlyCell(validationWorkSheet, value=u"Completed"), + WriteOnlyCell(validationWorkSheet, value=u"Stage"), + WriteOnlyCell( + validationWorkSheet, value=u"Heat Pre-validated"), + WriteOnlyCell(validationWorkSheet, value=u"Image Scan"), + WriteOnlyCell( + validationWorkSheet, value=u"AIC Instantiated"), + WriteOnlyCell( + validationWorkSheet, value=u"ASDC Onboarded"), + WriteOnlyCell( + validationWorkSheet, value=u"Overall Progress in %"), + WriteOnlyCell( + validationWorkSheet, value=u"Target Completion Date"), + WriteOnlyCell(validationWorkSheet, value=u"Status")] + for headline in headlines: + headline.font = Font(name='Courier', size=16, bold=True) + validationWorkSheet.append(headlines) + + for vf in vfs: + validationWorkSheet.append([smart_str(vf["engagement__engagement_manual_id"]), + smart_str(vf["vf__name"]), + smart_str( + vf["vf_engagement__reviewer"]), + smart_str( + vf["vf_engagement__peer_reviewer"]), + smart_str(vf["vfcs"]), + smart_str(vf["vfcs__number"]), + smart_str( + vf["engagement__started_state_time"]), + smart_str(vf["vendor__name"]), + smart_str( + vf["deployment_target__version"]), + smart_str(vf["ecomp_release__name"]), + smart_str( + vf["engagement__validated_time"]), + smart_str( + vf["engagement__completed_time"]), + smart_str( + vf["engagement__engagement_stage"]), + smart_str( + vf["engagement__heat_validated_time"]), + smart_str( + vf["engagement__image_scan_time"]), + smart_str( + vf["engagement__aic_instantiation_time"]), + smart_str( + vf["engagement__asdc_onboarding_time"]), + smart_str(vf["engagement__progress"]), + smart_str( + vf["engagement__target_completion_date"]), + smart_str( + vf["engagement__latest_status"]) + ]) + + # Create 'Overview' sheet and fill it up with required data: + overviewWorkSheet = workbook.create_sheet() + overviewWorkSheet.title = 'Overview' + headlines = [WriteOnlyCell(validationWorkSheet, value=u"AIC/ECOMP"), + WriteOnlyCell( + validationWorkSheet, value=u"Active Count of Engagement"), + WriteOnlyCell( + validationWorkSheet, value=u"Sum of Nr of VFs"), + WriteOnlyCell( + validationWorkSheet, value=u"Intake Count of Engagement"), + WriteOnlyCell( + validationWorkSheet, value=u"Sum of Nr of VFs"), + WriteOnlyCell( + validationWorkSheet, value=u"Completed Count of Engagement"), + WriteOnlyCell( + validationWorkSheet, value=u"Sum of Nr of VFs"), + WriteOnlyCell( + validationWorkSheet, value=u"Total Count of Engagement"), + WriteOnlyCell(validationWorkSheet, value=u"Total Sum of Nr of VFs")] + for headline in headlines: + headline.font = Font(name='Courier', size=16, bold=True) + overviewWorkSheet.append(headlines) + + for deployment_target in deployment_targets: + overviewWorkSheet.append(deployment_target) + + # We are using HttpResponse and not Rest Response since we couldnt find + # support for content diposition + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = 'attachment; filename=D2ICE.xlsx' + + workbook.save(response) + + return response + + +@classDecorator([logFuncEntry]) +class GetEngByUser(VvpApiView): + + @auth(Permissions.eng_membership) + def get(self, request): + user = request_data_mgr.get_user() + vf_list = [] + + engStageList = [EngagementStage.Intake.name, EngagementStage.Active.name, + EngagementStage.Validated.name, EngagementStage.Completed.name] # @UndefinedVariable + + # @UndefinedVariable + if (user.role.name == Roles.admin.name or user.role.name == Roles.admin_ro.name): + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList)\ + .distinct().order_by('engagement__engagement_manual_id')\ + .annotate( + engagement_manual_id=F('engagement__engagement_manual_id'), + engagement_uuid=F('engagement__uuid'), + vf_name=F('name'), + peer_reviewer__uuid=F('engagement__peer_reviewer__uuid'), + engagement_stage=F('engagement__engagement_stage'), + )\ + .values( + 'uuid', + 'vf_name', + 'engagement_manual_id', + 'engagement_uuid', + 'peer_reviewer__uuid', + 'engagement_stage', + ) + else: + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList).\ + filter(Q(engagement__engagement_team__uuid=user.uuid)).distinct().order_by('engagement__engagement_manual_id')\ + .annotate( + engagement_manual_id=F('engagement__engagement_manual_id'), + engagement_uuid=F('engagement__uuid'), + vf_name=F('name'), + peer_reviewer__uuid=F('engagement__peer_reviewer__uuid'), + reviewer__uuid=F('engagement__reviewer__uuid'), + engagement_stage=F('engagement__engagement_stage'), + )\ + .values( + 'uuid', + 'vf_name', + 'engagement_manual_id', + 'engagement_uuid', + 'peer_reviewer__uuid', + 'reviewer__uuid', + 'engagement_stage', + ) + + vf_final_array = [] + for vf in vf_list: + vfc_list = VFC.objects.filter(Q(vf=vf['uuid'])).values('name') + vf['vfc'] = [] + for vfc in vfc_list: + vf['vfc'].append(vfc['name']) + + vf['vfc'] = ', '.join(vf['vfc']) + vf_final_array.append(vf) + + return Response(vf_final_array) + + +@classDecorator([logFuncEntry]) +class SingleEngByUser(VvpApiView): + + @auth(Permissions.eng_membership) + def get(self, request, eng_uuid): + eng_uuid = request_data_mgr.get_eng_uuid() + user = request_data_mgr.get_user() + + engagement = None + + # @UndefinedVariable + if (user.role.name == Roles.admin.name or user.role.name == Roles.admin_ro.name): + engagement = Engagement.objects.get(uuid=eng_uuid) + else: + try: + engagement = Engagement.objects.get( + peer_reviewer=user, uuid=eng_uuid) + except Engagement.DoesNotExist: + try: + engagement = Engagement.objects.get( + engagement_team__uuid=user.uuid, uuid=eng_uuid) + except: + msg = "Eng for the User with uuid " + \ + user.uuid + " doesn't exist." + self.logger.error(msg) + msg = "Couldn't provide VF, internal server error" + return Response(msg, status=HTTP_500_INTERNAL_SERVER_ERROR) + vfObj = VF.objects.get(engagement__uuid=engagement.uuid) + eng_svc.update_or_insert_to_recent_engagements( + user.uuid, vfObj, RecentEngagementActionType.NAVIGATED_INTO_ENGAGEMENT.name) # @UndefinedVariable + + vfList = VF.objects.filter(engagement__uuid=engagement.uuid) + formated_vf_list = VFModelSerializer(vfList, many=True).data + formated_vf = formated_vf_list[0] + if vfObj.git_repo_url != str(-1): + formated_vf['files'] = GitManager().getRepoAssociatedFilesForUser( + eng_uuid) + else: + formated_vf['files'] = [] + + return Response(formated_vf) + + @auth(Permissions.edit_stage) + def put(self, request, eng_uuid, stage): + sts = HTTP_202_ACCEPTED + if not eng_uuid or not stage: + msg = "One of the Engagement's input parameters is missing" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + eng_uuid = request_data_mgr.get_eng_uuid() + msg = eng_svc.set_engagement_stage(eng_uuid, stage) + return Response(msg, status=sts) + + +@classDecorator([logFuncEntry]) +class ArchiveEngagement(VvpApiView): + + @auth(Permissions.archive_engagement) + def put(self, request, eng_uuid): + data = request.data + eng_uuid = request_data_mgr.get_eng_uuid() + msg = eng_svc.archive_engagement(eng_uuid, data['reason']) + return Response(msg) + + +@classDecorator([logFuncEntry]) +class StarredEngagements(VvpApiView): + + @auth(Permissions.star_an_engagement) + def get(self, request): + user = request_data_mgr.get_user() + if (user == None): + msg = "User with uuid " + user.uuid + \ + " doesn't exist. Can't fetch their engagements" + self.logger.error(logEncoding(msg)) + msg = "You are not registered as a user, please sign up in order to perform this action" + return Response(msg, status=HTTP_400_BAD_REQUEST) + + vf_list = eng_svc.vf_retreiver(user, True) + if not vf_list: + msg = "Action succeeded, no starred VFs were found." + self.logger.debug(msg) + return Response(msg, status=HTTP_204_NO_CONTENT) + + vfListData = [] + + for vf_data in vf_list: + + # @UndefinedVariable + if (user.role.name == Roles.el.name or user.role.name == Roles.admin.name or user.role.name == Roles.admin_ro.name): + if (vf_data['engagement__reviewer__uuid'] == user.uuid): + checklist_lists = Checklist.objects.filter(Q(engagement__uuid=vf_data['engagement__uuid']), Q(engagement__reviewer=user), ~Q( + state=CheckListState.archive.name)).values('uuid', 'name', 'state', 'owner__uuid') # @UndefinedVariable + # @UndefinedVariable + elif (user.role.name == Roles.admin.name or user.role.name == Roles.admin_ro.name): + checklist_lists = Checklist.objects.filter(Q(engagement__uuid=vf_data['engagement__uuid']), ~Q( + state=CheckListState.archive.name)).values('uuid', 'name', 'state', 'owner__uuid') # @UndefinedVariable + else: + checklist_lists = Checklist.objects.filter(Q(engagement__uuid=vf_data['engagement__uuid']), Q(owner=user), ~Q( + state=CheckListState.archive.name)).values('uuid', 'name', 'state', 'owner__uuid') # @UndefinedVariable + vf_data['checklists'] = checklist_lists + else: + vf_data['checklists'] = None + + vfListData.append(vf_data) + + return Response(vfListData) + + @auth(Permissions.star_an_engagement) + def put(self, request, **kwargs): + user = request_data_mgr.get_user() + data = request.data + sts = HTTP_200_OK + if ('engagement_uuid' not in data or not data['engagement_uuid']): + msg = "starred engagement uuid parameter is missing" + self.logger.error(msg) + msg = "Action was failed due to bad request." + return Response(msg, status=HTTP_400_BAD_REQUEST) + + eng_uuid = data['engagement_uuid'] + if (user == None): + msg = "User with uuid " + user.uuid + \ + " doesn't exist. Can't fetch their engagements" + self.logger.error(logEncoding(msg)) + msg = "You are not registered as a user, please sign up in order to perform this action" + return Response(msg, status=HTTP_400_BAD_REQUEST) + + msg = eng_svc.star_an_engagement(user, eng_uuid) + + return Response(msg, status=sts) + + +@classDecorator([logFuncEntry]) +class GetRecentEngagements(VvpApiView): + + @auth(Permissions.eng_membership) + def get(self, request, format=None, **kwargs): + user = request_data_mgr.get_user() + if (user == None): + msg = "User with uuid " + user.uuid + \ + " doesn't exist. Can't fetch their engagements" + self.logger.error(logEncoding(msg)) + msg = "You are not registered as a user, please sign up in order to perform this action" + return Response(msg, status=HTTP_400_BAD_REQUEST) + + stared_list = eng_svc.vf_retreiver(user, True) + + vf_list = eng_svc.vf_retreiver(user, False, True) + + if not vf_list: + msg = "Action succeeded, no recent VFs were found." + self.logger.debug(msg) + return Response(msg, status=HTTP_204_NO_CONTENT) + + vfListData = [] + recentList = 20 + stared_list.count() + for idx, vf_data in enumerate(vf_list): + if (idx == recentList): + break + # @UndefinedVariable + if (user.role.name == Roles.el.name or user.role.name == Roles.admin.name or user.role.name == Roles.admin_ro.name): + if (vf_data['vf__engagement__reviewer__uuid'] == user.uuid): + checklist_lists = Checklist.objects.filter(Q(engagement__uuid=vf_data['vf__engagement__uuid']), Q(engagement__reviewer=user), ~Q( + state=CheckListState.archive.name)).values('uuid', 'name', 'state', 'owner__uuid') # @UndefinedVariable + # @UndefinedVariable + elif (user.role.name == Roles.admin.name or user.role.name == Roles.admin_ro.name): + checklist_lists = Checklist.objects.filter(Q(engagement__uuid=vf_data['vf__engagement__uuid']), ~Q( + state=CheckListState.archive.name)).values('uuid', 'name', 'state', 'owner__uuid') # @UndefinedVariable + else: + checklist_lists = Checklist.objects.filter(Q(engagement__uuid=vf_data['vf__engagement__uuid']), Q(owner=user), ~Q( + state=CheckListState.archive.name)).values('uuid', 'name', 'state', 'owner__uuid') # @UndefinedVariable + vf_data['checklists'] = checklist_lists + else: + vf_data['checklists'] = None + vfListData.append(vf_data) + return Response(vfListData) + + +@classDecorator([logFuncEntry]) +class EngagementProgressBar(VvpApiView): + + @auth(Permissions.edit_progress_bar) + def put(self, request, eng_uuid): + data = request.data + msg = "OK" + + if ('progress' not in data or not data['progress'] or data['progress'] == ''): + msg = "progress parameter is missing or empty" + self.logger.error(msg) + msg = "Action has failed due to bad request." + return Response(msg, status=HTTP_400_BAD_REQUEST) + + eng_svc.set_progress_for_engagement(progress=data['progress']) + return Response(msg, status=HTTP_202_ACCEPTED) + + @auth(Permissions.get_progress_bar) + def post(self, request, eng_uuid): + data = request.data + eng = self.get_entity(Engagement, request_data_mgr.get_eng_uuid()) + msg = "OK" + + if ('target_date' not in data or not data['target_date'] or data['target_date'] == ''): + msg = "target_date parameter is missing or empty" + self.logger.error(msg) + msg = "Action has failed due to bad request." + return Response(msg, status=HTTP_400_BAD_REQUEST) + + target_date = data['target_date'] + date = parse_date(target_date) + eng.target_completion_date = date + eng.save() + return Response(msg) + + +@classDecorator([logFuncEntry]) +class ChangeTargetLabEntryDate(VvpApiView): + + @auth(Permissions.change_lab_entry) + def post(self, request, eng_uuid): + data = request.data + eng = self.get_entity(Engagement, request_data_mgr.get_eng_uuid()) + msg = "OK" + vf = VF.objects.get(engagement__uuid=eng.uuid) + if ('target_date' not in data or not data['target_date'] or data['target_date'] == ''): + msg = "target_date parameter is missing or empty" + self.logger.error(msg) + msg = "Action has failed due to bad request." + return Response(msg, status=HTTP_400_BAD_REQUEST) + + target_date = data['target_date'] + date = parse_date(target_date) + vf.target_lab_entry_date = date + vf.save() + return Response(msg) + + +@classDecorator([logFuncEntry, ]) +class Status(VvpApiView): + + @auth(Permissions.get_engagement_status) + def get(self, request, eng_uuid): + eng_uuid = request_data_mgr.get_eng_uuid() + engagement = Engagement.objects.get(uuid=eng_uuid) + latest_status = EngagementStatus.objects.filter( + engagement=engagement).distinct().order_by('-update_time')[:1] + if (latest_status.count() > 0): + latest_status = latest_status[0] + latest_status = EngagementStatusModelSerializer(latest_status).data + else: + latest_status = False + return Response(latest_status) + + @auth(Permissions.put_engagement_status) + def put(self, request, eng_uuid): + user = request_data_mgr.get_user() + data = request.data + + eng_uuid = request_data_mgr.get_eng_uuid() + eng_status_uuid = data['eng_status_uuid'] + description = data['description'] + + if not description: + msg = "Not description sent" + self.logger.error(msg) + msg = "You are not registered as a user, please sign up in order to perform this action" + return Response(msg, status=HTTP_400_BAD_REQUEST) + + # @UndefinedVariable + if (user.role.name != Roles.admin.name and user.role.name != Roles.el.name): + msg = "User not authorized" + self.logger.error(msg) + msg = "Internal error." + return Response(msg, status=HTTP_401_UNAUTHORIZED) + + engagement = Engagement.objects.get(uuid=eng_uuid) + status = EngagementStatus.objects.get(uuid=eng_status_uuid) + eng_svc.update_engagement_status( + user, description, eng_status_uuid, engagement) + + status = EngagementStatus.objects.get(uuid=eng_status_uuid) + status = EngagementStatusModelSerializer(status).data + + return Response(status) + + @auth(Permissions.put_engagement_status) + def post(self, request, eng_uuid): + user = request_data_mgr.get_user() + eng_uuid = request_data_mgr.get_eng_uuid() + data = request.data + + description = data['description'] + if not description: + msg = "No description sent" + self.logger.error(msg) + msg = "No description sent" + return Response(msg, status=HTTP_400_BAD_REQUEST) + + # @UndefinedVariable + if (user.role.name != Roles.admin.name and user.role.name != Roles.el.name): + msg = "User not authorized" + self.logger.error(msg) + msg = "Internal error." + return Response(msg, status=HTTP_401_UNAUTHORIZED) + engagement = Engagement.objects.get(uuid=eng_uuid) + created_eng_staus = eng_svc.insert_engagement_status( + user, description, engagement) + created_eng_staus = EngagementStatusModelSerializer( + created_eng_staus).data + return Response(created_eng_staus) + + +@classDecorator([logFuncEntry]) +class EngagementOps(VvpApiView): + + @auth(Permissions.update_engagement) + def put(self, request, eng_uuid): + data = request.data + engagement_dict = data['engagement'] + engagement = eng_svc.update_engagement(engagement_dict) + + if engagement is None: + return Response(status=HTTP_400_BAD_REQUEST) + else: + if 'status' in data and data['status']: + user = request_data_mgr.get_user() + created_eng_status = eng_svc.insert_engagement_status( + user, data['status'], engagement) + return Response(EngagementStatusModelSerializer(created_eng_status).data) + else: + return Response() + + +@classDecorator([logFuncEntry]) +class EngagementTeamUsers(VvpApiView): + + @auth(Permissions.remove_from_engagement_team) + def put(self, request): + eng_uuid = request_data_mgr.get_eng_uuid() + user = request_data_mgr.get_user() + data = request.data + if (data['user_uuid']): + requested_user_uuid = data['user_uuid'] + if (eng_uuid is not None and user is not None and data['user_uuid'] is not None): + eng_svc.remove_user_from_engagement_team( + eng_uuid, user, requested_user_uuid) + return Response(status=HTTP_204_NO_CONTENT) + + +@classDecorator([logFuncEntry]) +class EngagementReviewer(VvpApiView): + + @auth(Permissions.update_engagement_reviewers) + def put(self, request, eng_uuid): + data = request.data + eng_uuid = request_data_mgr.get_eng_uuid() + reviewer = eng_svc.set_engagement_reviewer(eng_uuid, data['reviewer']) + + if reviewer is None: + return Response(status=HTTP_500_INTERNAL_SERVER_ERROR) + else: + return Response(reviewer) + + +@classDecorator([logFuncEntry]) +class EngagementPeerReviewer(VvpApiView): + + @auth(Permissions.update_engagement_reviewers) + def put(self, request, eng_uuid): + data = request.data + eng_uuid = request_data_mgr.get_eng_uuid() + peer_reviewer = eng_svc.set_engagement_peer_reviewer( + eng_uuid, data['peerreviewer']) + + if peer_reviewer is None: + return Response(status=HTTP_500_INTERNAL_SERVER_ERROR) + else: + return Response(peer_reviewer) + + +@classDecorator([logFuncEntry]) +class SwitchEngagementReviewers(VvpApiView): + + @auth(Permissions.update_engagement_reviewers) + def put(self, request, eng_uuid): + data = request.data + eng_uuid = request_data_mgr.get_eng_uuid() + resp = eng_svc.switch_engagement_reviewers( + eng_uuid, data['reviewer'], data['peerreviewer']) + if resp is None: + return Response(status=HTTP_500_INTERNAL_SERVER_ERROR) + else: + return Response(resp) diff --git a/django/engagementmanager/rest/feedback.py b/django/engagementmanager/rest/feedback.py new file mode 100755 index 0000000..b8075b8 --- /dev/null +++ b/django/engagementmanager/rest/feedback.py @@ -0,0 +1,70 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework import status +from rest_framework.response import Response + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.slack_client.api import SlackClient +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.models import Feedback as FeedbackModal + + +@classDecorator([logFuncEntry]) +class Feedback(VvpApiView): + + slack_client = SlackClient() + + @auth(Permissions.add_feedback) + def post(self, request): + user = request_data_mgr.get_user() + if ('description' not in request.data or not request.data['description']): + raise KeyError("One of the input parameters are missing") + new_description = request.data['description'] + new_feedback = FeedbackModal( + user=user, + description=new_description + ) + new_feedback.save() + self.slack_client.send_slack_notifications_for_new_feedback(new_feedback, user) + + return Response(status.HTTP_200_OK) diff --git a/django/engagementmanager/rest/invite.py b/django/engagementmanager/rest/invite.py new file mode 100755 index 0000000..8060a69 --- /dev/null +++ b/django/engagementmanager/rest/invite.py @@ -0,0 +1,97 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from rest_framework import status +from rest_framework.response import Response + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.invite_service import inviteUserToSignUpOrLogin +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.utils.validator import logEncoding + + +@classDecorator([logFuncEntry]) +class InviteTeamMember(VvpApiView): + + @auth(Permissions.invite) + def post(self, request): + inviterUser = request_data_mgr.get_user() + msg = "OK" + sts = status.HTTP_200_OK + if (inviterUser != None): + dataList = [] + dataList = request.data + + for data in dataList: + if 'eng_uuid' in data and data['eng_uuid'] and 'email' in data and data['email']: + inviteUserToSignUpOrLogin(inviterUser, data, is_contact_user=False) + else: + msg = "No eng_uuid or no email found on the request body to invite-team-members. data=" + str(data) + self.logger.error(logEncoding(msg)) + sts = status.HTTP_500_INTERNAL_SERVER_ERROR + + return Response(msg, status=sts) + + +@classDecorator([logFuncEntry]) +class InviteContact(VvpApiView): + + @auth(Permissions.invite) + def post(self, request): + msg = "OK" + sts = status.HTTP_200_OK + data = request.data + + if ('full_name' not in data or not data['full_name'] or + 'email' not in data or not data['email'] or + 'phone_number' not in data or not data['phone_number'] or + 'eng_uuid' not in data or not data['eng_uuid']): + msg = "One of the input parameters is missing" + self.logger.error(msg) + return Response(msg, status=status.HTTP_400_BAD_REQUEST) + + inviterUser = request_data_mgr.get_user() + inviteUserToSignUpOrLogin(inviterUser, data, is_contact_user=True) + + return Response(msg, status=sts) diff --git a/django/engagementmanager/rest/login.py b/django/engagementmanager/rest/login.py new file mode 100755 index 0000000..53b906b --- /dev/null +++ b/django/engagementmanager/rest/login.py @@ -0,0 +1,88 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import IceUserProfile +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.login_service import LoginSvc +from engagementmanager.utils.authentication import JWTAuthentication + + +@classDecorator([logFuncEntry]) +class Login(VvpApiView): + permission_classes = (AllowAny,) + + def post(self, request, param): + data = request.data + jwt_obj = JWTAuthentication() + msg = "" + user_profile = IceUserProfile.objects.get(email=data['email']) + login_svc = LoginSvc() + + reset_password_param = None + if param: + reset_password_param = param + + reset_password_email, is_reset_pwd_flow = login_svc.identify_reset_password(jwt_obj, reset_password_param) + + if not user_profile.user.is_active: + msg = login_svc.render_user_not_active_message(data['email']) + else: + if is_reset_pwd_flow: + msg = login_svc.reset_password( + reset_password_email, data['password'], msg, user_profile) + else: + user_profile.user.User = login_svc.authenticate_user( + data['email'], data['password'], msg) + + msg = login_svc.get_serialized_user_data( + is_reset_pwd_flow, user_profile, jwt_obj, user_profile.user) + + if 'invitation' in data: + login_svc.handle_invite_token(data, msg, user_profile) + + self.logger.debug("login has passed successfully for [email=" + data['email'] + "]") + login_svc.update_last_login(user_profile) + + return Response(msg) diff --git a/django/engagementmanager/rest/nextsteps.py b/django/engagementmanager/rest/nextsteps.py new file mode 100755 index 0000000..7d4f850 --- /dev/null +++ b/django/engagementmanager/rest/nextsteps.py @@ -0,0 +1,163 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from rest_framework.response import Response +from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_204_NO_CONTENT + +from engagementmanager.bus.messages.activity_event_message import ActivityEventMessage +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import NextStep +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.utils.activities_data import DeleteNextStepsActivityData +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.nextstep_service import NextStepSvc +from engagementmanager.utils.constants import NextStepState +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.apps import bus_service + + +@classDecorator([logFuncEntry]) +class UserNextSteps(VvpApiView): + + def get(self, request): + data_or_msg, count = NextStepSvc().get_user_next_steps( + 5, NextStepState.Incomplete.name) # @UndefinedVariable + return Response({'data': data_or_msg.data, 'count': count}) + + +@classDecorator([logFuncEntry]) +class NextSteps(VvpApiView): + + @auth(Permissions.set_nextstep) + def post(self, request, **kwargs): + dataList = request.data + eng_uuid = request_data_mgr.get_eng_uuid() + user = request_data_mgr.get_user() + + for data in dataList: + if ('description' not in data or not data['description']): + msg = "One of the input parameters is missing" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + + data = NextStepSvc().addNextStep(dataList) + + for next_step in data: + if (next_step['files'] != None): + next_step['files'] = json.loads(next_step['files']) + + self.logger.debug("Successfully added a Next Step to engagement_uuid=" + + eng_uuid + " for creator with uuid=" + str(user)) + return Response(data) + + @auth(Permissions.eng_membership) + def get(self, request, **kwargs): + next_steps_data = NextStepSvc().get_next_steps(eng_stage=kwargs['eng_stage']) + return Response(next_steps_data.data) + + @auth(Permissions.update_personal_next_step) + def put(self, request, **kwargs): + data = request.data + ns_state = attribute = None + if ('attr' in kwargs): + attribute = kwargs['attr'] + if ('state' in data): + ns_state = data['state'] + NextStepSvc().set_next_step_status(attr=attribute, state=ns_state) + return Response() + + +@classDecorator([logFuncEntry]) +class OrderNextSteps(VvpApiView): + + @auth(Permissions.order_nextstep) + def put(self, request, eng_uuid): + data = request.data + NextStepSvc().update_next_steps_order(nextsteps=data) + return Response() + + +@classDecorator([logFuncEntry]) +class EditNextSteps(VvpApiView): + @auth(Permissions.edit_nextstep) + def put(self, request, ns_uuid): + data = request.data + NextStepSvc().update_next_step(data) + return Response() + + @auth(Permissions.delete_nextstep) + def delete(self, request, ns_uuid): + ns = self.get_entity(NextStep, request_data_mgr.get_ns_uuid()) + ns.delete() + + activity_data = DeleteNextStepsActivityData(request_data_mgr.get_user(), ns.engagement) + bus_service.send_message(ActivityEventMessage(activity_data)) + + return Response(status=HTTP_204_NO_CONTENT) + + +@classDecorator([logFuncEntry]) +class ChecklistNextStep(VvpApiView): + + @auth(Permissions.add_checklist_nextstep) + def post(self, request, eng_uuid, checklistUuid): + body_unicode = request.body + dataList = json.loads(body_unicode) + msg = "OK" + + if (request_data_mgr.get_cl_uuid() == None or request_data_mgr.get_eng_uuid() == None): + msg = "check list uuid or engagement uuid is missing from the url path parameters" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + + for data in dataList: + if ('assigneesUuids' not in data or not data['assigneesUuids'] or + 'description' not in data or not data['description'] or + 'duedate' not in data or not data['duedate']): + msg = "One of the CheckList's input parameters is missing" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + + data = NextStepSvc().addNextStep( + dataList, desc="Checklist is denied due to a creation of a new NextStep") + + return Response(data) diff --git a/django/engagementmanager/rest/notification.py b/django/engagementmanager/rest/notification.py new file mode 100755 index 0000000..34c4a7b --- /dev/null +++ b/django/engagementmanager/rest/notification.py @@ -0,0 +1,89 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.response import Response +from rest_framework.status import HTTP_204_NO_CONTENT,\ + HTTP_400_BAD_REQUEST + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +import engagementmanager.models +from engagementmanager.notifications import num_of_notifications_for_user, reset_num_of_notifications_for_user,\ + pull_recent_notifications +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.utils.request_data_mgr import request_data_mgr + + +@classDecorator([logFuncEntry]) +class PullNotifCount4User(VvpApiView): + + def get(self, request): + user = request_data_mgr.get_user() + dataToJson = {} + notificationCtr = num_of_notifications_for_user(user.uuid) + dataToJson['notifications_number'] = str(notificationCtr) + return Response(dataToJson) + + +@classDecorator([logFuncEntry]) +class NotificationOps(VvpApiView): + + @auth(Permissions.delete_notification) + def delete(self, request, notif_uuid): + notif = self.get_entity( + engagementmanager.models.Notification, notif_uuid) + notif.delete() + return Response(status=HTTP_204_NO_CONTENT) + + # PullRecentNotif4User + def get(self, request, user_uuid, offset, limit): + user = request_data_mgr.get_user() + serilizedActivitySet, num_of_objects = pull_recent_notifications(user.uuid, offset, limit) + if serilizedActivitySet is not None: + data = {'serilizedActivitySet': serilizedActivitySet, 'num_of_objects': num_of_objects} + return Response(data) + else: + return Response("Activity set wasn't found", status=HTTP_400_BAD_REQUEST) + + # Reset the number of an unread notifications + def put(self, request): + user = request_data_mgr.get_user() + reset_num_of_notifications_for_user(user.uuid) + return Response() diff --git a/django/engagementmanager/rest/parsers.py b/django/engagementmanager/rest/parsers.py new file mode 100755 index 0000000..fce516a --- /dev/null +++ b/django/engagementmanager/rest/parsers.py @@ -0,0 +1,118 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework import parsers +from bleach.sanitizer import Cleaner +from django.http.request import QueryDict + + +sanitizer = Cleaner( + tags=['a', 'b', 'i', 'p', 'span', 'div'], + attributes=['font-weight', 'href', 'style', 'bold'], + styles=[ + 'color', 'font-family', 'font-style', 'font-weight', + 'text-decoration-line', + ], + protocols=['http'], + strip=True, + ) + + +def clean_r(obj): + """Apply bleach.clean() to strings in the given object, recursively. + + Note that this applies clean() to keys as well as values. + """ + + # DataAndFiles objects: recurse on .data, passthrough .files + if isinstance(obj, parsers.DataAndFiles): + return parsers.DataAndFiles(clean_r(obj.data), obj.files) + + # QueryDict: make new empty mutable object. Update, make immutable, return. + if isinstance(obj, QueryDict): + new_obj = QueryDict(mutable=True, encoding=obj.encoding) + for k, v in obj.lists(): + new_obj.setlistdefault(sanitizer.clean(k)).extend(clean_r(v)) + new_obj._mutable = False + return new_obj + + # dict-like objects: clean keys, recursive-clean values + if callable(getattr(obj, "items", None)): + return obj.__class__( + (sanitizer.clean(k), clean_r(v)) + for k, v in obj.items()) + + # string-like objects: clean + if isinstance(obj, str): + return sanitizer.clean(obj) + + # list-like objects / iterables: recurse on all items + if callable(getattr(obj, "__iter__", None)): + return obj.__class__(clean_r(x) for x in obj) + + # anything else: pass through + return obj + + +class XSSParserMixin(parsers.BaseParser): + """Apply this mixin to rest_framework.parsers.BaseParser subclasses to + cause clean_r() to be run against the parsed data. + + """ + def parse(self, stream, media_type=None, parser_context=None): + return clean_r( + super().parse( + stream, + media_type=media_type, + parser_context=parser_context)) + + +class XSSJSONParser(XSSParserMixin, parsers.JSONParser): + pass + + +class XSSFormParser(XSSParserMixin, parsers.FormParser): + pass + + +class XSSMultiPartParser(XSSParserMixin, parsers.MultiPartParser): + pass + + +# There's no need to XSS-scrub FileUploadParser since its DataAndFiles.data is +# always empty. diff --git a/django/engagementmanager/rest/signup.py b/django/engagementmanager/rest/signup.py new file mode 100755 index 0000000..85d63cd --- /dev/null +++ b/django/engagementmanager/rest/signup.py @@ -0,0 +1,188 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import uuid + +from django.template.loader import get_template +from django.utils import timezone +from rest_framework import status +from rest_framework.parsers import JSONParser +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from engagementmanager import mail +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import Vendor, Engagement, Role, Invitation, \ + IceUserProfile, CustomUser +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import SuperThinIceUserProfileModelSerializer +from engagementmanager.service.invite_service import markInvitationAsAccepted +from engagementmanager.service.user_service import UserService +from engagementmanager.utils.authentication import JWTAuthentication +from engagementmanager.utils.constants import Constants, Roles +from engagementmanager.utils.validator import Validator, logEncoding +from engagementmanager.views_helper import generateActivationLink, \ + createUserTemplate + + +@classDecorator([logFuncEntry]) +class SignUp(VvpApiView): + permission_classes = (AllowAny,) + + def post(self, request): + data = request.data + data_dont_save = JSONParser().parse(request) + + if ('company' not in data or not data['company'] or + 'full_name' not in data or not data['full_name'] or + 'email' not in data or not data['email'] or + 'password' not in data or not data['password'] or + 'phone_number' not in data or not data['phone_number'] or + 'regular_email_updates' not in data): + msg = "One of the input parameters is missing" + self.logger.error(msg) + return Response(msg, status=status.HTTP_400_BAD_REQUEST) + + Validator.validatePassword(data['password']) + + i_full_name = data['full_name'] + i_email = data['email'] + i_phone_number = data['phone_number'] + i_password = data['password'] + i_regular_email_updates = data['regular_email_updates'] + i_is_service_provider_contact = False + + add_without_confirm = False + + user_svc = UserService() + + if 'add_from_import_excel' in data: + add_without_confirm = True + + Validator.validateEmail(i_email) + + if data_dont_save['company'] == Constants.service_provider_company_name: + i_is_service_provider_contact = True + + mailTokens = i_email.split("@") + if mailTokens[1] not in Constants.service_provider_mail_domain and i_is_service_provider_contact: + msg = "Email address should be with service provider domain for signees that their company =" + \ + Constants.service_provider_company_name + self.logger.error(logEncoding(msg)) + return Response(msg, status=status.HTTP_400_BAD_REQUEST) + + iceuser = IceUserProfile.objects.filter(email=i_email) + if (not iceuser.exists()): + roleObj = Role.objects.get( + name=Roles.standard_user.name) # @UndefinedVariable + activationToken = str(uuid.uuid4().hex) + i_company = Vendor.objects.get(name=data_dont_save['company']) + + user_object = CustomUser.objects.create_user(username=i_email, email=i_email, password=i_password, + activation_token=activationToken, activation_token_create_time=timezone.now(), is_active=False) + info = createUserTemplate(i_company, i_full_name, roleObj, i_phone_number, + i_is_service_provider_contact, None, i_regular_email_updates, user_object) + newUserObj, is_profile_created = IceUserProfile.objects.update_or_create( + email=user_object.email, defaults=info) + + self.logger.debug( + "Creating Non activated User: " + str(newUserObj)) + userData = SuperThinIceUserProfileModelSerializer(newUserObj).data + # If we eng_uuid and inviter_uuid is supplied it means that this user was + # invited. We want to add them to the engagement team of the inviter + + if 'invitation' in data: + invitation = Invitation.objects.get( + invitation_token=data['invitation']) + self.logger.debug("Looks like user " + i_full_name + " has arrived to the sign-up page from an invite email initiated by user with uuid=" + + invitation.invited_by_user_uuid + ". Adding them to the inviter's engagement_team...") + + userData['eng_uuid'] = invitation.engagement_uuid + if data["is_contact_user"] == "true": + engObj = Engagement.objects.get( + uuid=invitation.engagement_uuid) + engObj.contact_user = newUserObj + self.logger.debug("Attaching the user (" + newUserObj.full_name + + ") to the engagement's (" + engObj.uuid + ") contact_user") + engObj.save() + + user_svc.addUserToEngAndFireProvisionVfSig( + newUserObj, invitation) + + otherInviteObj = Invitation.objects.filter( + accepted=False, email=i_email).exclude(uuid=invitation.uuid) + + if data['is_contact_user'] == "true" or data['is_contact_user'] == "True": + engObj = Engagement.objects.get( + uuid=invitation.engagement_uuid) + engObj.contact_user = newUserObj + self.logger.debug("Attaching the user (" + newUserObj.full_name + + ") to the engagement's (" + engObj.uuid + ") contact_user") + engObj.save() + + markInvitationAsAccepted(data['invitation']) + for inviteObj in otherInviteObj: + user_svc.addUserToEngAndFireProvisionVfSig( + newUserObj, inviteObj) + markInvitationAsAccepted(inviteObj.invitation_token) + + if (add_without_confirm): + newUserObj.is_active = True + newUserObj.save() + else: + data['activation_link'] = generateActivationLink( + activationToken, newUserObj) + self.logger.debug( + "Activation Link: " + data['activation_link']) + + body = get_template("{activate_template_dir}activate_mail_body.html".format( + activate_template_dir=Constants.activate_template_dir)) + subject = get_template("{activate_template_dir}activate_mail_subject.html".format( + activate_template_dir=Constants.activate_template_dir)) + mail.sendMail(i_email, data, body, subject) + + self.logger.debug( + "sign-up has passed successfully for [email=" + i_email + "]") + + return Response(userData) + else: + msg = "email " + i_email + \ + " already exists, no need to perform signup, try to login" + self.logger.info(logEncoding(msg)) + return Response(msg, status=status.HTTP_409_CONFLICT) diff --git a/django/engagementmanager/rest/user.py b/django/engagementmanager/rest/user.py new file mode 100755 index 0000000..13fc916 --- /dev/null +++ b/django/engagementmanager/rest/user.py @@ -0,0 +1,241 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import uuid + +from django.conf import settings +from django.contrib.auth.hashers import make_password +from django.template.loader import get_template +from rest_framework.parsers import JSONParser +from rest_framework.permissions import AllowAny +from rest_framework.response import Response +from rest_framework.status import HTTP_400_BAD_REQUEST +from rest_framework.status import HTTP_500_INTERNAL_SERVER_ERROR + +from engagementmanager import mail +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import IceUserProfile, Vendor +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import ThinIceUserProfileModelSerializer +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.user_service import UserService +from engagementmanager.utils.authentication import JWTAuthentication +from engagementmanager.utils.constants import Constants +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.utils.validator import Validator +from engagementmanager.vm_integration import vm_client + + +@classDecorator([logFuncEntry]) +class SetSsh(VvpApiView): + + def post(self, request): + user = request_data_mgr.get_user() + data = request.data + if 'ssh_key' in data and data['ssh_key'] != user.ssh_public_key: + user_service = UserService() + user_service.validate_ssh_key(data['ssh_key']) + user_service.setSSH(user, data['ssh_key'], 'set') + user.save() + vm_client.fire_event_in_bg( + 'send_ssh_key_created_or_updated_event', user) + return Response() + + +@classDecorator([logFuncEntry]) +class UpdatePassword(VvpApiView): + + def put(self, request): + data = request.data + msg = "OK" + Validator.validatePassword(data['password'], data['confirm_password']) + user = request_data_mgr.get_user() + user.user.set_password(data['password']) + user.user.temp_password = None + user.user.save() + self.logger.info("Reset Password finished successfully for user with uuid=" + + user.uuid + " Redirecting to Login") + return Response(msg) + + +@classDecorator([logFuncEntry]) +class SendResetPasswordInstructionMail(VvpApiView): + permission_classes = (AllowAny,) + + def post(self, request): + msg = "OK" + user = None + data = request.data + + if ('email' not in data or not data['email']): + msg = "Email address is missing" + self.logger.error(msg) + return Response(msg, status=HTTP_400_BAD_REQUEST) + + Validator.validateEmail(data['email']) + + user = IceUserProfile.objects.get(email=data['email']) + jwt_obj = JWTAuthentication() + token = jwt_obj.create_reset_password_token(user.user) + + data['tempPassword'] = str(uuid.uuid1()).split("-")[0] + data['login_link'] = str( + settings.DOMAIN) + "/#/login?t=" + str(token) + self.logger.debug( + "The login link to reset Password: " + str(data['login_link'])) + + if (user != None): + body = get_template("{reset_pwd_template_dir}reset_pwd_instructions_mail_body.html" .format( + reset_pwd_template_dir=Constants.reset_pwd_template_dir)) + subject = get_template("{reset_pwd_template_dir}reset_pwd_instructions_mail_subject.html".format( + reset_pwd_template_dir=Constants.reset_pwd_template_dir)) + + user.user.temp_password = make_password(data['tempPassword']) + user.user.save() + user.save() + + try: + mail.sendMail(data['email'], data, body, subject) + except Exception as e: + msg = "Something went wrong while trying to send reset-password mail to " + \ + data['email'] + "\n error: " + e.message + self.logger.error( + msg + " rolling back the temporary password from the DB") + user.user.temp_password = None + user.save() + return Response(msg, status=HTTP_500_INTERNAL_SERVER_ERROR) + return Response(msg) + + +@classDecorator([logFuncEntry]) +class User(VvpApiView): + + def get(self, request): + user = request_data_mgr.get_user() + return Response(ThinIceUserProfileModelSerializer(user).data) + + def put(self, request): + data_dont_save = JSONParser().parse(request) + data = request.data + errors_list = [] + self.validate_mandatory_fields(data, errors_list) + user = request_data_mgr.get_user() + user.company = Vendor.objects.get(name=data_dont_save['company']) + user.phone_number = data['phone_number'] + user.full_name = data['full_name'] + if len(user.full_name) > 30: + return Response("first name should be up to 30 characters", status=HTTP_400_BAD_REQUEST) + + self.handle_password_change(data, user) + + ssh_changed = self.handle_ssh_change(data, user) + + self.handle_notifications_settings_change(data, user) + + if len(errors_list) != 0: + return Response(errors_list, status=HTTP_400_BAD_REQUEST) + + user.save() + + if ssh_changed: + vm_client.fire_event_in_bg( + 'send_ssh_key_created_or_updated_event', user) + + userData = ThinIceUserProfileModelSerializer(user).data + self.logger.info( + "Account updated successfully for user with uuid=" + user.uuid) + userData['password'] = "" + return Response(userData) + + def handle_notifications_settings_change(self, data, user): + if 'regular_email_updates' in data: + user.regular_email_updates = data['regular_email_updates'] + if 'email_updates_daily_digest' in data: + user.email_updates_daily_digest = data[ + 'email_updates_daily_digest'] + if 'email_updates_on_every_notification' in data: + user.email_updates_on_every_notification = data[ + 'email_updates_on_every_notification'] + + def handle_ssh_change(self, data, user): + ssh_changed = False + if 'ssh_key' in data and data['ssh_key'] != user.ssh_public_key: + user_service = UserService() + user_service.validate_ssh_key(data['ssh_key']) + if not user.ssh_public_key: + user_service.setSSH(user, data['ssh_key'], 'add') + else: + user_service.setSSH(user, data['ssh_key'], 'set') + if data['ssh_key']: + ssh_changed = True + return ssh_changed + + def handle_password_change(self, data, user): + if 'password' in data and data['password']: + Validator.validatePassword( + data['password'], data['confirm_password']) + user.user.set_password(data['password']) + user.user.save() + + def validate_mandatory_fields(self, data, errors_list): + if ('company' not in data or not data['company'] or + 'full_name' not in data or not data['full_name'] or + 'email' not in data or not data['email'] or + 'phone_number' not in data or not data['phone_number']): + msg = "One of the input parameters is missing. #" + errors_list.append(msg) + self.logger.error(msg) + + +@classDecorator([logFuncEntry]) +class EngagementLeads(VvpApiView): + + @auth(Permissions.archive_engagement) + def get(self, request): + el_list = UserService().get_el_list() + return Response(el_list) + + +@classDecorator([logFuncEntry]) +class RGWAAccessKey(VvpApiView): + + def get(self, request): + return Response({"rgwa_secret_key": UserService().get_user_rgwa_secret()}) diff --git a/django/engagementmanager/rest/validation_details.py b/django/engagementmanager/rest/validation_details.py new file mode 100755 index 0000000..1f1a929 --- /dev/null +++ b/django/engagementmanager/rest/validation_details.py @@ -0,0 +1,55 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.response import Response + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.views_helper import updateValidationDetails + + +@classDecorator([logFuncEntry]) +class UpdateValidationDetails(VvpApiView): + + @auth(Permissions.update_vf) + def put(self, request, vf_uuid): + updateValidationDetails(request) + return Response() diff --git a/django/engagementmanager/rest/vendor.py b/django/engagementmanager/rest/vendor.py new file mode 100755 index 0000000..b6ae351 --- /dev/null +++ b/django/engagementmanager/rest/vendor.py @@ -0,0 +1,95 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.permissions import AllowAny, IsAuthenticatedOrReadOnly +from rest_framework.response import Response +from rest_framework.status import HTTP_409_CONFLICT, HTTP_204_NO_CONTENT + +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import Vendor +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import ThinVendorModelSerializer + + +@classDecorator([logFuncEntry]) +class VendorREST(VvpApiView): + permission_classes = (IsAuthenticatedOrReadOnly,) + + def get(self, request): + self.permission_classes = (AllowAny,) + vendors = Vendor.objects.filter(public=True) + serializer = ThinVendorModelSerializer(vendors, many=True) + return Response(serializer.data) + + """ + expecting: Vendor object fields + result: addition of a Vendor object to the DB + """ + + def post(self, request): + msg = "" + sts = None + data = request.data + + vendor = None + public = False + if 'public' in data: + public = data['public'] + try: + vendor = Vendor.objects.get(name=data['name']) + msg = "Company: " + vendor.name + " already exist" + self.logger.error(msg) + sts = HTTP_409_CONFLICT + return Response(msg, status=sts) + # If the VFC Does not exist, then continue as usual and create it. + except Vendor.DoesNotExist: + company = Vendor.objects.create(name=data['name'], public=False) + company.save() + return Response(msg) + + """ + expecting: Vendor object uuid + result: Deletion of the Vendor object from the DB + """ + + def delete(self, request, uuid): + msg = "" + sts = HTTP_204_NO_CONTENT + vendor = Vendor.objects.get(uuid=uuid).delete() + return Response(msg, status=sts) diff --git a/django/engagementmanager/rest/vf.py b/django/engagementmanager/rest/vf.py new file mode 100755 index 0000000..23ee5b9 --- /dev/null +++ b/django/engagementmanager/rest/vf.py @@ -0,0 +1,74 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.response import Response +from rest_framework.status import HTTP_400_BAD_REQUEST + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.vf_service import VFSvc +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.utils.validator import logEncoding +from engagementmanager.views_helper import createVF + + +@classDecorator([logFuncEntry]) +class VF(VvpApiView): + + vf_svc = VFSvc() + + @auth(Permissions.add_vf) + def post(self, request): + user = request_data_mgr.get_user() + vfList = [] + if user is not None: + vfList = createVF(user, request) + return Response(vfList) + else: + msg = "User wasn't found on top of the kwargs" + sts = HTTP_400_BAD_REQUEST + self.logger.error(logEncoding(msg)) + msg = "Action Failed" + return Response(msg, status=sts) + + def get(self, request, vf_uuid): + vf_version = self.vf_svc.get_vf_version(vf_uuid) + return Response(vf_version) diff --git a/django/engagementmanager/rest/vfc.py b/django/engagementmanager/rest/vfc.py new file mode 100755 index 0000000..9ebf3bc --- /dev/null +++ b/django/engagementmanager/rest/vfc.py @@ -0,0 +1,86 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from rest_framework.response import Response +from rest_framework.status import HTTP_204_NO_CONTENT + +from engagementmanager.decorator.auth import auth +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.models import VF, VFC +from engagementmanager.rest.vvp_api_view import VvpApiView +from engagementmanager.serializers import VFCModelSerializer +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.vfc_service import VFCSvc + + +@classDecorator([logFuncEntry]) +class VFCRest(VvpApiView): + vfc_service = VFCSvc() + + @auth(Permissions.get_vfc) + def get(self, request, vf_uuid): + + vf = VF.objects.get(uuid=vf_uuid) + vfcs = VFC.objects.filter(vf=vf) + serializer = VFCModelSerializer(vfcs, many=True) + return Response(serializer.data) + + """ + expecting: VF object uuid, VFC relevant fields(excluding the ones with default field) + result: addition of a VFC to the DB and concatenating them with the VF object + """ + # This method doesn't need to be decorated with auth since it doesn't pass any engagement data from the front-end + + @auth(Permissions.add_vfc) + def post(self, request): + data = request.data + msg = self.vfc_service.create_vfc(data) + return Response(msg) + + """ + expecting: VFC object uuid + result: Deletion of the VFC object with vfc_uuid + """ + + @auth(Permissions.delete_vfc) + def delete(self, request, vf_uuid, vfc_uuid): + self.vfc_service.delete_vfc(vfc_uuid) + return Response(status=HTTP_204_NO_CONTENT) diff --git a/django/engagementmanager/rest/vvp_api_view.py b/django/engagementmanager/rest/vvp_api_view.py new file mode 100755 index 0000000..4abe086 --- /dev/null +++ b/django/engagementmanager/rest/vvp_api_view.py @@ -0,0 +1,64 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from abc import ABCMeta +from rest_framework.views import APIView +from engagementmanager.decorator.class_decorator import classDecorator +from engagementmanager.decorator.log_func_entry import logFuncEntry +from engagementmanager.service.authorization_service import AuthorizationService +from engagementmanager.service.logging_service import LoggingServiceFactory + + +@classDecorator([logFuncEntry]) +class VvpApiView(APIView): + ''' + classdocs This is the base abstract class of all ice REST views + ''' + __metaclass__ = ABCMeta + + logger = LoggingServiceFactory.get_logger() + + def initial(self, request, *args, **kwargs): + super(VvpApiView, self).initial(request, *args, **kwargs) + auth_service = AuthorizationService() + args += request, + auth_service.prepare_data_for_auth(*args, **kwargs) + + def get_entity(self, entity_name, uuid): + entity = entity_name.objects.get(uuid=uuid) + return entity diff --git a/django/engagementmanager/scheduled_jobs.py b/django/engagementmanager/scheduled_jobs.py new file mode 100755 index 0000000..9430ff6 --- /dev/null +++ b/django/engagementmanager/scheduled_jobs.py @@ -0,0 +1,67 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from apscheduler.schedulers.background import BackgroundScheduler +from django.conf import settings +from engagementmanager.bus.messages.daily_scheduled_message import DailyScheduledMessage +from engagementmanager.bus.messages.hourly_scheduled_message import HourlyScheduledMessage +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class ScheduledJobs: + def __init__(self, bus_service): + self.bus_service = bus_service + self.background_scheduler = BackgroundScheduler() + self.background_scheduler.start() + + def __daily_scheduled_job(self): + logger.debug("Daily scheduled job is about to start.") + self.bus_service.send_message(DailyScheduledMessage()) + + def setup_daily_job(self): + self.background_scheduler.add_job(self.__daily_scheduled_job, 'cron', + hour=settings.DAILY_SCHEDULED_JOB_HOUR, day='*') + + def __hourly_scheduled_job(self): + logger.debug("Hourly scheduled job is about to start.") + self.bus_service.send_message(HourlyScheduledMessage()) + + def setup_hourly_job(self): + self.background_scheduler.add_job(self.__hourly_scheduled_job, 'cron', minute=0, hour='*', day='*') diff --git a/django/engagementmanager/serializers.py b/django/engagementmanager/serializers.py new file mode 100755 index 0000000..e3e88b0 --- /dev/null +++ b/django/engagementmanager/serializers.py @@ -0,0 +1,423 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +''' +Each entity has a model serializer that save/update the object in its create()/update() methods and a regular dictionary (map) serializer that return a new/updated instance of the object + +''' +from rest_framework import serializers + +from engagementmanager.models import NextStep, Notification, Activity, \ + ChecklistTemplate, Checklist, ChecklistAuditLog, ChecklistDecision, \ + ChecklistLineItem, ECOMPRelease, EngagementStatus, CustomUser, \ + ChecklistSection + +from .models import IceUserProfile, VFC, Engagement, VF, DeploymentTarget, Role, Vendor, DeploymentTargetSite + + +class RoleModelSerializer(serializers.ModelSerializer): + + class Meta: + model = Role + fields = '__all__' + + +class VendorModelSerializer(serializers.ModelSerializer): + + class Meta: + model = Vendor + fields = '__all__' + + +class ThinVendorModelSerializer(serializers.ModelSerializer): + + class Meta: + model = Vendor + fields = ('uuid', 'name') + + +class SuperThinCustomUserModelSerializer(serializers.ModelSerializer): + + class Meta: + model = CustomUser + fields = ('is_active', 'email', 'activation_token') + + +class ThinCustomUserModelSerializer(serializers.ModelSerializer): + + class Meta: + model = CustomUser + fields = ('email', 'activation_token', 'is_active', + 'activation_token_create_time') + + +class IceUserProfileModelSerializer(serializers.ModelSerializer): + role = RoleModelSerializer(many=False) + company = VendorModelSerializer(many=False) + user = ThinCustomUserModelSerializer(many=False) + + class Meta: + model = IceUserProfile + + +class SuperThinIceUserProfileModelSerializer(serializers.ModelSerializer): + role = RoleModelSerializer(many=False) + company = VendorModelSerializer(many=False) + user = SuperThinCustomUserModelSerializer(many=False) + + class Meta: + model = IceUserProfile + fields = ('full_name', 'email', 'uuid', 'role', + 'user', 'company', 'phone_number') + + +class SuperThinIceUserProfileModelSerializerForSignals(serializers.ModelSerializer): + role = RoleModelSerializer(many=False) + + class Meta: + model = IceUserProfile + fields = ('full_name', 'email', 'role', 'uuid', 'ssh_public_key') + + +class ThinIceUserProfileModelSerializer(serializers.ModelSerializer): + role = RoleModelSerializer(many=False) + company = VendorModelSerializer(many=False) + user = SuperThinCustomUserModelSerializer(many=False) + + class Meta: + model = IceUserProfile + fields = ('email', 'full_name', 'user', 'is_service_provider_contact', 'phone_number', 'role', 'uuid', 'company', + 'ssh_public_key', 'regular_email_updates', 'email_updates_on_every_notification', + 'email_updates_daily_digest', 'rgwa_access_key') + + +class EngagementStatusModelSerializer(serializers.ModelSerializer): + creator = SuperThinIceUserProfileModelSerializer(many=False) + + class Meta: + model = EngagementStatus + fields = '__all__' + + +class EngagementModelSerializer(serializers.ModelSerializer): + engagement_team = SuperThinIceUserProfileModelSerializer(many=True) + contact_user = SuperThinIceUserProfileModelSerializer(many=False) + creator = SuperThinIceUserProfileModelSerializer(many=False) + peer_reviewer = SuperThinIceUserProfileModelSerializer(many=False) + reviewer = SuperThinIceUserProfileModelSerializer(many=False) + starred_engagement = SuperThinIceUserProfileModelSerializer(many=True) + + class Meta: + model = Engagement + fields = '__all__' + + +class ThinEngagementModelSerializer(serializers.ModelSerializer): + creator = SuperThinIceUserProfileModelSerializer(many=False) + engagement_team = SuperThinIceUserProfileModelSerializer(many=True) + peer_reviewer = SuperThinIceUserProfileModelSerializer(many=False) + reviewer = SuperThinIceUserProfileModelSerializer(many=False) + + class Meta: + model = Engagement + fields = ('uuid', 'engagement_manual_id', 'creator', + 'engagement_team', 'peer_reviewer', 'reviewer') + + +class DeploymentTargetModelSerializer(serializers.ModelSerializer): + + class Meta: + model = DeploymentTarget + fields = ('uuid', 'name', 'version', 'weight', 'ui_visibility') + + +class ECOMPReleaseModelSerializer(serializers.ModelSerializer): + + class Meta: + model = ECOMPRelease + fields = ('uuid', 'name', 'weight', 'ui_visibility') + + +class ThinVFModelSerializer(serializers.ModelSerializer): + engagement = ThinEngagementModelSerializer(many=False) + + class Meta: + model = VF + fields = ( + 'uuid', 'name', 'engagement', 'is_service_provider_internal', 'ecomp_release') + + +class ThinDeploymentTargetSiteModelSerializer(serializers.ModelSerializer): + + class Meta: + model = DeploymentTargetSite + fields = ('uuid', 'name') + + +class DeploymentTargetSiteModelSerializer(serializers.ModelSerializer): + + class Meta: + model = DeploymentTargetSite + fields = '__all__' + + +class VFModelSerializer(serializers.ModelSerializer): + engagement = EngagementModelSerializer(many=False) + deployment_target = DeploymentTargetModelSerializer(many=False) + ecomp_release = ECOMPReleaseModelSerializer(many=False) + deployment_target_sites = ThinDeploymentTargetSiteModelSerializer( + many=True) + vendor = VendorModelSerializer(many=False) + + class Meta: + model = VF + fields = '__all__' + + +class VFCModelSerializer(serializers.ModelSerializer): + + class Meta: + model = VFC + fields = '__all__' + + +class ActivityModelSerializer(serializers.ModelSerializer): + + class Meta: + model = Activity + fields = '__all__' + + +class ThinActivityModelSerializer(serializers.ModelSerializer): + + class Meta: + model = Activity + fields = ('uuid', 'description', 'create_time', 'metadata') + + +class NotificationModelSerializer(serializers.ModelSerializer): + activity = ActivityModelSerializer(many=False) + + class Meta: + model = Notification + fields = '__all__' + + +class ThinNotificationModelSerializer(serializers.ModelSerializer): + activity = ThinActivityModelSerializer(many=False) + + class Meta: + model = Notification + fields = '__all__' + + +class ChecklistTemplateModelSerializer(serializers.ModelSerializer): + + class Meta: + model = ChecklistTemplate + exclude = ('create_time', 'update_time', 'category', 'version') + + +class ThinChecklistTemplateModelSerializer(serializers.ModelSerializer): + + class Meta: + model = ChecklistTemplate + fields = ('uuid', 'name') + + +class ChecklistModelSerializer(serializers.ModelSerializer): + + class Meta: + model = Checklist + fields = '__all__' + + +class SuperThinChecklistModelSerializer(serializers.ModelSerializer): + owner = ThinIceUserProfileModelSerializer(many=False) + + class Meta: + model = Checklist + fields = ('uuid', 'name', 'state', 'owner') + + +class ThinChecklistModelSerializer(serializers.ModelSerializer): + engagement = ThinEngagementModelSerializer(many=False) + template = ThinChecklistTemplateModelSerializer(many=False) + owner = ThinIceUserProfileModelSerializer(many=False) + + class Meta: + model = Checklist + fields = ('uuid', 'name', 'state', 'owner', 'weight', + 'associated_files', 'engagement', 'template') + + +class ThinPostChecklistResponseModelSerializer(serializers.ModelSerializer): + template = ThinChecklistTemplateModelSerializer(many=False) + + class Meta: + model = Checklist + fields = ('uuid', 'name', 'state', 'associated_files', 'template') + + +class UserNextStepModelSerializer(serializers.ModelSerializer): + engagement_manual_id = serializers.CharField( + source='engagement.engagement_manual_id') + engagement_uuid = serializers.CharField(source='engagement.uuid') + creator_full_name = serializers.CharField(source='creator.full_name') + vf_name = serializers.CharField(source='engagement.vf.name') + + class Meta: + model = NextStep + fields = ('due_date', 'engagement_manual_id', 'description', + 'create_time', 'creator_full_name', 'vf_name', 'engagement_uuid') + + +class NextStepModelSerializer(serializers.ModelSerializer): + engagement = EngagementModelSerializer(many=False) + creator = SuperThinIceUserProfileModelSerializer(many=False) + last_updater = SuperThinIceUserProfileModelSerializer(many=False) + assignees = SuperThinIceUserProfileModelSerializer(many=True) + + class Meta: + model = NextStep + fields = '__all__' + + +class ThinNextStepModelSerializer(serializers.ModelSerializer): + assignees = SuperThinIceUserProfileModelSerializer(many=True) + last_updater = SuperThinIceUserProfileModelSerializer(many=False) + + class Meta: + ordering = ('position') + model = NextStep + fields = '__all__' + + +class TestEngineChecklistModelSerializer(serializers.ModelSerializer): + template_id = serializers.CharField(source='template.uuid') + engagement_manual_id = serializers.CharField( + source='engagement.engagement_manual_id') + engagement_id = serializers.CharField(source='engagement.uuid') + creator_id = serializers.CharField(source='engagement.creator.uuid') + + class Meta: + model = Checklist + fields = ('uuid', 'state', 'associated_files', 'template_id', + 'engagement_manual_id', 'engagement_id', 'creator_id') + + +class ChecklistAuditLogModelSerializer(serializers.ModelSerializer): + + class Meta: + model = ChecklistAuditLog + fields = '__all__' + + +class ThinChecklistAuditLogModelSerializer(serializers.ModelSerializer): + creator = SuperThinIceUserProfileModelSerializer(many=False) + + class Meta: + model = ChecklistAuditLog + fields = ('uuid', 'category', 'description', 'create_time', 'creator') + + +class ChecklistSectionModelSerializer(serializers.ModelSerializer): + + class Meta: + model = ChecklistSection + exclude = ('template', 'parent_section', 'create_time', 'update_time') + + +class ChecklistLineItemModelSerializer(serializers.ModelSerializer): + + class Meta: + model = ChecklistLineItem + exclude = ('section', 'template', 'create_time', 'update_time') + + +class ThinChecklistSectionModelSerializer(serializers.ModelSerializer): + + class Meta: + model = ChecklistLineItem + fields = ('uuid', 'name', 'weight', 'description') + + +class ThinChecklistLineItemModelSerializer(serializers.ModelSerializer): + section = ThinChecklistSectionModelSerializer(many=False) + + class Meta: + model = ChecklistLineItem + fields = ('uuid', 'name', 'line_type', 'weight', + 'description', 'validation_instructions', 'section') + + +class ThinChecklistDecisionModelSerializer(serializers.ModelSerializer): + lineitem = ThinChecklistLineItemModelSerializer(many=False) + + class Meta: + model = ChecklistDecision + fields = ('uuid', 'review_value', 'peer_review_value', 'lineitem') + + +class EngagementModelSerializerForSignal(serializers.ModelSerializer): + engagement_team = SuperThinIceUserProfileModelSerializerForSignals( + many=True) + contact_user = SuperThinIceUserProfileModelSerializerForSignals(many=False) + creator = SuperThinIceUserProfileModelSerializerForSignals(many=False) + peer_reviewer = SuperThinIceUserProfileModelSerializerForSignals( + many=False) + reviewer = SuperThinIceUserProfileModelSerializerForSignals(many=False) + starred_engagement = SuperThinIceUserProfileModelSerializerForSignals( + many=True) + + class Meta: + model = Engagement + fields = '__all__' + + +class VFModelSerializerForSignal(serializers.ModelSerializer): + engagement = EngagementModelSerializerForSignal(many=False) + deployment_target = DeploymentTargetModelSerializer(many=False) + ecomp_release = ECOMPReleaseModelSerializer(many=False) + deployment_target_sites = ThinDeploymentTargetSiteModelSerializer( + many=True) + vendor = VendorModelSerializer(many=False) + + class Meta: + model = VF + fields = '__all__' diff --git a/django/engagementmanager/service/__init__.py b/django/engagementmanager/service/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/service/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/service/activities_service.py b/django/engagementmanager/service/activities_service.py new file mode 100755 index 0000000..b7edca4 --- /dev/null +++ b/django/engagementmanager/service/activities_service.py @@ -0,0 +1,238 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from django.utils import timezone +from engagementmanager.bus.messages.new_notification_message import NewNotificationMessage +from engagementmanager.models import IceUserProfile, Activity, Notification +from engagementmanager.utils import activities_data +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class ActivitiesSvc: + def __init__(self): + pass + + def generate_activity(self, activity_data): + if hasattr(activity_data, "users_list") and activity_data.users_list: + for user in activity_data.users_list: + activity_data.user = user + if hasattr(activity_data, "multiple_users_as_owners") and activity_data.multiple_users_as_owners: + activity_data.owner = activity_data.user + self.set_description(activity_data) + self.set_metadata(activity_data) + self.__create_activity(activity_data) + else: + self.set_description(activity_data) + self.set_metadata(activity_data) + self.__create_activity(activity_data) + + def __create_activity(self, activity_data): + if activity_data.engagement is None: + msg = "Engagement provided is a None object, be careful not to generate " \ + "description and metadata with engagement properties." + logger.warn(msg) + if activity_data.owner and not isinstance(activity_data.owner, IceUserProfile): + raise ValueError("owner should be IceUserProfile, was %r", activity_data.owner) + if activity_data.description is None: + logger.warn('createActivity called with description=None; setting to ""') + activity_data.description = '' + + new_activity = Activity.objects.create( + activity_owner=activity_data.owner, + description=activity_data.description, + is_notification=activity_data.is_notification, + engagement=activity_data.engagement, + activity_type=activity_data.activity_type.name, + metadata=json.dumps(activity_data.metadata, ensure_ascii=False),) + + if activity_data.engagement: + activity_data.engagement.activity_set.add(new_activity) + new_activity.save() + + if activity_data.is_notification: + users_to_notify = [] + + if activity_data.owner is None: + if activity_data.engagement: + users_to_notify = activity_data.engagement.engagement_team.all() + else: + users_to_notify.append(activity_data.owner) + + for user_to_notify in users_to_notify: + new_notification = Notification.objects.create(user=user_to_notify, activity=new_activity) + new_activity.notification_set.add(new_notification) + user_to_notify.notification_set.add(new_notification) + new_notification.save() + from engagementmanager.apps import bus_service + bus_service.send_message(NewNotificationMessage(new_notification)) + + def pull_recent_activities(self, engagement, recent_activities_limit): + """ expected: engagement object (Activity), recent_activities_limit (integer) - number of recent activities + result: Top-X Dict Activity objects (sort by create_time) """ + logger.debug("Pulling top X activities from DB") + activities = Activity.objects.filter( + engagement=engagement, activity_owner=None).order_by('-create_time')[:recent_activities_limit] + return activities + + def set_description(self, activity_data): + dt = timezone.now() + description = '' + + if isinstance(activity_data, activities_data.UserJoinedEngagementActivityData): + description = "##user_name## joined ##vf_name## " + elif isinstance(activity_data, activities_data.UpdateNextStepsActivityData): + description = "##user_name## " + activity_data.update_type.lower() + " a next step" + elif isinstance(activity_data, activities_data.VFProvisioningActivityData): + description = "Failed Gitlab and/or Jenkins Provision ##vf_name##: " + activity_data.description + elif isinstance(activity_data, activities_data.TestFinishedActivityData): + description = "Failure in Jenkins Job: " + activity_data.description + elif isinstance(activity_data, activities_data.ChangeEngagementStageActivityData): + description = "Engagement stage is now " + activity_data.stage + " for the following VF: ##vf_name##" + elif isinstance(activity_data, activities_data.DeleteNextStepsActivityData): + description = activity_data.user.full_name + \ + " has deleted a next step at " + dt.strftime("%Y-%m-%d %H:%M:%S") + elif isinstance(activity_data, activities_data.NoticeEmptyEngagementData): + description = "You have not added any parts of the VNF package to your engagement ##vf_name## since it was created " + activity_data.delta_days_from_creation +\ + " days ago. Do note that if you have not added any parts of the VNF package by " + \ + activity_data.max_empty_time + ", we will be automatically archive it." + elif isinstance(activity_data, activities_data.AddNextStepsActivityData): + description = activity_data.user.full_name + " has added a next step at " + dt.strftime("%Y-%m-%d %H:%M:%S") + elif isinstance(activity_data, activities_data.SSHKeyAddedActivityData): + if activity_data.action == 'add': + description = "You have added an SSH key to your profile" + elif activity_data.action == 'set': + description = "You have set a new SSH key in your profile" + else: + description = "SSH key activity" + + activity_data.description = description + + def set_metadata(self, activity_data): + dt = timezone.now() + metadata = {} + + if isinstance(activity_data, activities_data.UserJoinedEngagementActivityData): + activity_data.is_notification = True + metadata['notification_subject'] = "Someone has joined the " + activity_data.vf.name + " team" + metadata['notification_message'] = activity_data.user.full_name + " joined the " + activity_data.vf.name + \ + " team. You can reach the dashboard by going to this link: " + \ + Constants.dashboard_href + metadata['macros'] = { + '##vf_name##': { + 'type': 'select_engagement', + 'short': activity_data.vf.name, + 'eng_uuid': str(activity_data.engagement.uuid), + }, + '##user_name##': { + 'type': 'popover', + 'short': activity_data.user.full_name, + 'long': activity_data.user.email, + } + } + elif isinstance(activity_data, activities_data.UpdateNextStepsActivityData): + metadata['macros'] = { + '##user_name##': { + 'type': 'popover', + 'short': activity_data.user.full_name, + 'long': activity_data.user.email, + } + } + elif isinstance(activity_data, activities_data.NoticeEmptyEngagementData): + activity_data.is_notification = True + metadata['notification_subject'] = "Inactive Engagement Alert - " + activity_data.vf_name + + metadata['notification_message'] = "We have noticed that you have not added any parts of the VNF package to your engagement <em>" +\ + activity_data.engagement.engagement_manual_id + ": " + activity_data.vf_name + "</em> since it was created " + activity_data.delta_days_from_creation +\ + " days ago. If you have any questions around how you add your VNF package please check the relevant parts of the online documentation.<br/><br/>" +\ + "Do note that if you have not added any parts of the VNF package by " + \ + activity_data.max_empty_time + ", we will be automatically archive it." + + metadata['macros'] = { + '##vf_name##': { + 'type': 'select_engagement', + 'short': activity_data.vf_name, + 'eng_uuid': activity_data.engagement.uuid, + }, + } + + elif isinstance(activity_data, activities_data.VFProvisioningActivityData): + activity_data.is_notification = True + metadata['notification_subject'] = "Failed Gitlab and/or Jenkins Provision: " + activity_data.vf.name + metadata['notification_message'] = activity_data.description + metadata['macros'] = { + '##vf_name##': { + 'type': 'select_engagement', + 'short': activity_data.vf.name, + 'eng_uuid': activity_data.vf.engagement.uuid, + }, + } + elif isinstance(activity_data, activities_data.TestFinishedActivityData): + activity_data.is_notification = True + metadata['notification_subject'] = "Failed test_finished signal " + metadata['notification_message'] = activity_data.description + elif isinstance(activity_data, activities_data.ChangeEngagementStageActivityData): + activity_data.is_notification = True + metadata['notification_subject'] = "Engagement stage was changed for the following VF: " + \ + activity_data.vf.name + metadata['notification_message'] = "Engagement stage is now " + activity_data.stage +\ + " for the following VF: " + activity_data.vf.name + metadata['macros'] = { + '##vf_name##': { + 'type': 'select_engagement', + 'short': activity_data.vf.name, + 'eng_uuid': activity_data.engagement.uuid, + } + } + elif isinstance(activity_data, activities_data.AddNextStepsActivityData): + activity_data.is_notification = True + metadata['notification_subject'] = "New next-step was added to the following VF: " + activity_data.vf.name + metadata['notification_message'] = activity_data.user.full_name + " has added a next step at " +\ + dt.strftime("%Y-%m-%d %H:%M:%S") + \ + ", You can reach the dashboard by going to this link: " \ + + Constants.dashboard_href + elif isinstance(activity_data, activities_data.SSHKeyAddedActivityData): + activity_data.is_notification = True + metadata['notification_subject'] = "You have set an SSH key" + metadata['notification_message'] = "You have set an SSH key to your profile. Please allow some time for" \ + " it to propagate across the system." + + activity_data.metadata = metadata diff --git a/django/engagementmanager/service/authorization_service.py b/django/engagementmanager/service/authorization_service.py new file mode 100755 index 0000000..c850b4a --- /dev/null +++ b/django/engagementmanager/service/authorization_service.py @@ -0,0 +1,605 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from enum import Enum +import rest_framework +from engagementmanager.models import Role, Engagement, Checklist, NextStep, VFC, \ + VF, ChecklistDecision, Notification +from engagementmanager.utils.constants import Roles +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class Permissions(Enum): + """ + This ENUM holds all the actions that require permissions on the ICE portal + """ + update_user = 1, # TODO Any user can update their own account + add_vendor = 2, # only el or admin + add_nextstep = 3, # only el or admin + complete_nextstep = 4, # any eng member + delete_nextstep = 5, # only el or admin + approve_nextstep = 6, # only el or admin + deny_nextstep = 7, # only el or admin + reset_nextstep = 8 # any eng member + add_checklist = 9, # only el of a given engagement + set_checklist_decision = 10, # TODO only el defined as owner of cl + add_checklist_audit_log = 11, # TODO only el defined as owner of cl + delete_checklist_audit_log = 12, # Do we have this capability ?? + el_review_checklist = 13, # only checklist owner can set state. + # only el defined as peer_viewer of given engagement and is cl owner + peer_review_checklist = 14, + # TODO only admin which is defined as cl owner + admin_approve_checklist = 15, + # TODO only el of a given engagement and is the cl owner + handoff_checklist = 16, + add_vf = 17, # only standard_user + add_vfc = 18, # only standard_user ?? + delete_vfc = 19, # only standard_user + add_checklist_nextstep = 20, # only el + is_el_of_eng = 21, # only el of engagement + update_personal_next_step = 22, + create_checklist_audit_log = 23, + create_checklist_decision = 24, + update_checklist_decision = 25, + update_checklist_state = 26, + create_deployment_target_site = 27, + star_an_engagement = 28, + invite = 29, + update_account = 30, + set_ssh = 31, + update_password = 32, + get_engagement_status = 34, + put_engagement_status = 35, + eng_membership = 36, + delete_engagement = 37, + view_checklist = 38, # only non-standard-user + get_vfc = 39, + pull_activities = 40, + get_deployment_target_site = 41, + add_deployment_target_site = 42, + delete_deployment_target_site = 43, + export_engagments = 44, + archive_engagement = 45, + get_el_list = 46, + update_engagement = 47, + view_checklist_template = 48, + edit_checklist_template = 49, + delete_notification = 50, + remove_from_engagement_team = 51, + update_engagement_reviewers = 52, + edit_nextstep = 54, + order_nextstep = 60, + set_nextstep = 56, + edit_stage = 57, + edit_progress_bar = 58, + get_progress_bar = 59, + change_lab_entry = 62, + update_vf = 61, # only non-standard-user + add_feedback = 63, + + +class AuthorizationService: + """ + The Authorization Service detemines whether a given action is authorized for a specific user. + The method: is_user_able_to performs the authorization check given a user and an action (from Permissions ENUM) + """ + role_standard_user = None + role_el = None + role_admin = None + role_admin_ro = None + + def __get_role_checks(self, user, action): + """ + Returns the list of auth checks that should be performed per user action. + Returns None if the action is not listed in the authorized actions of the given user. + """ + result = None + + # EL # + if (user.role == self.role_el) and (action in self.el_permissions): + result = self.el_permissions[action] + # ADMIN # + elif user.role == self.role_admin and action in self.admin_permissions: + result = self.admin_permissions[action] + # ADMIN Read only # + elif user.role == self.role_admin_ro and action in self.admin_ro_permissions: + result = self.admin_ro_permissions[action] + # STANDRARD_USER # + if user.role == self.role_standard_user and action in self.standard_user_permissions: + result = self.standard_user_permissions[action] + + return result + + def __require_eng_membership(self, user, action, **kwargs): + """ + Determines whether a given user is part of engagement team by the eng uuid + user = IceUser + eng = UUID as a string + + :param user: user for auth check + :param action: action for auth check + :param kwargs: eng_uuid, checklist_uuid, ... + :return: Boolean, Message -> True/False if auth check succeeds/fails and a message describing auth failure + """ + eng = kwargs['eng'] + + try: + # @UndefinedVariable + if (user.email == eng.reviewer.email or user.email == eng.peer_reviewer.email or user.role.name == Roles.admin.name): + return True, 'OK' + else: + # validate if user in Team + if user in eng.engagement_team.all(): + return True, 'OK' + else: + return False, "" + except Engagement.DoesNotExist: + msg = 'User ' + user.email + ' is not a member of engagement: ' + eng.uuid + \ + ' / User is a not peer reviewer / admin of the engagement / Engagement wasnt found while fetching from DB' + logger.info(msg) + return False, msg + except Exception as e: + print(e) + msg = 'A general error occurred while trying to validate that User ' + \ + user.email + ' is a member of engagement ' + logger.info(msg + " Error: " + str(e)) + return False, msg + + def __require_peer_review_ownership(self, user, action, **kwargs): + """ + Determines whether the given user is the peer reviewer of the checklist + """ + + cl = kwargs['cl'] + eng = kwargs['eng'] + if cl and eng: + # @UndefinedVariable + if (eng.peer_reviewer == user and cl.owner == user) or (user.role.name == Roles.admin.name): + return True, 'OK' + else: + return False, 'User is either not the owner of the checklist or not a peer reviewer of the checklist' + else: + logger.error( + 'Internal Error - Checklist/Engagement not found while trying to check permissions for user ' + user.email) + return False, 'Internal Error - Checklist not found' + + def __require_cl_ownership(self, user, action, **kwargs): + """ + Determines whether the given user is the owner of the checklist + """ + + cl = kwargs['cl'] + if cl: + # @UndefinedVariable + if cl.owner == user or user.role.name == Roles.admin.name: + return True, 'OK' + else: + return False, 'User is not the owner of the checklist' + else: + logger.error( + 'Internal Error - Checklist not found while trying to check permissions for user ' + user.email) + return False, 'Internal Error - Checklist not found' + + def __require_el_of_engagement(self, user, action, **kwargs): + """ + Determines whether the given user is the el of the engagement + """ + eng = kwargs['eng'] + + if eng: + if (user.role.name == Roles.admin.name): # @UndefinedVariable + return True, 'OK' + if (user.uuid == eng.reviewer.uuid): # @UndefinedVariable + return True, 'OK' + + return False, 'Role Not authorized' + else: + logger.error( + 'Internal Error - Engagement not found while trying to check permissions for user ' + user.email) + return False, 'Internal Error - Checklist not found' + + def __noop(self, user, action, **kwargs): + """ + Do nothing, just authorize the action for the given user + """ + return True, 'OK' + + def __prevent(self, user, action, **kwargs): + """ + Do nothing, just prevent the action for the given user + """ + return False, 'Role Not authorized' + + def __is_notification_owner(self, user, action, **kwargs): + msg = 'Role Not authorized' + authorized = False + + notification_uuid = request_data_mgr.get_notification_uuid() + if notification_uuid: + if Notification.objects.get(uuid=notification_uuid).user == user: + authorized = True + msg = 'OK' + + return authorized, msg + + ###################### + # EL Permissions # + ###################### + """ + Each Permission Map is composed of the following key-val pairs: + Key='Action (Permission ENUM)' --> Value='Set of Checks to perform on this action.' + """ + el_permissions = { + Permissions.add_vf: {__noop}, + Permissions.add_feedback: {__noop}, + Permissions.update_user: {__noop}, + Permissions.add_vendor: {__noop}, + Permissions.update_vf: {__require_eng_membership}, + Permissions.add_nextstep: {__require_eng_membership}, + Permissions.complete_nextstep: {__require_eng_membership}, + Permissions.delete_nextstep: {__require_eng_membership}, + Permissions.order_nextstep: {__require_eng_membership}, + Permissions.set_nextstep: {__require_eng_membership}, + Permissions.edit_stage: {__require_eng_membership}, + Permissions.edit_progress_bar: {__require_eng_membership}, + Permissions.get_progress_bar: {__require_eng_membership}, + Permissions.change_lab_entry: {__require_eng_membership}, + Permissions.approve_nextstep: {__require_eng_membership}, + Permissions.deny_nextstep: {__require_eng_membership}, + Permissions.add_checklist: {__require_eng_membership}, + Permissions.set_checklist_decision: {__require_cl_ownership}, + Permissions.add_checklist_audit_log: {__require_cl_ownership}, + Permissions.delete_checklist_audit_log: {__require_cl_ownership}, + Permissions.el_review_checklist: {__require_cl_ownership, __require_eng_membership}, + Permissions.peer_review_checklist: {__require_peer_review_ownership}, + Permissions.handoff_checklist: {__require_cl_ownership, __require_eng_membership}, + Permissions.add_checklist_nextstep: {__require_cl_ownership, __require_eng_membership}, + Permissions.edit_nextstep: {__require_eng_membership}, + Permissions.is_el_of_eng: {__require_el_of_engagement}, + Permissions.update_personal_next_step: {__noop}, + Permissions.create_checklist_audit_log: {__require_eng_membership}, + Permissions.create_checklist_decision: {__require_eng_membership}, + Permissions.update_checklist_state: {__require_cl_ownership, __require_eng_membership}, + Permissions.create_deployment_target_site: {__require_eng_membership}, + Permissions.star_an_engagement: {__noop}, + Permissions.invite: {__require_eng_membership}, + Permissions.update_account: {__require_eng_membership}, + Permissions.set_ssh: {__require_eng_membership}, + Permissions.update_password: {}, + Permissions.delete_vfc: {__require_eng_membership}, + Permissions.get_engagement_status: {__require_eng_membership}, + Permissions.put_engagement_status: {__require_eng_membership}, + Permissions.eng_membership: {__noop}, + Permissions.delete_engagement: {__require_eng_membership}, + Permissions.view_checklist: {__require_eng_membership}, + Permissions.pull_activities: {__require_eng_membership}, + Permissions.get_deployment_target_site: {__noop}, + Permissions.add_deployment_target_site: {__noop}, + Permissions.delete_deployment_target_site: {__noop}, + Permissions.export_engagments: {__noop}, + Permissions.update_checklist_decision: {__noop}, + Permissions.get_vfc: {__noop}, + Permissions.add_vfc: {__noop}, + Permissions.delete_notification: {__is_notification_owner}, + Permissions.update_engagement: {__noop}, + Permissions.remove_from_engagement_team: {__require_eng_membership}, + } + + ################################# + # STANDARD_USER Permissions # + ################################# + standard_user_permissions = { + Permissions.update_user: {__noop}, + Permissions.add_vf: {__noop}, + Permissions.add_feedback: {__noop}, + Permissions.add_vfc: {__noop}, + Permissions.get_vfc: {__require_eng_membership}, + Permissions.delete_vfc: {__require_eng_membership}, + Permissions.complete_nextstep: {__require_eng_membership}, + Permissions.update_vf: {__require_eng_membership}, + Permissions.reset_nextstep: {__require_eng_membership}, + Permissions.update_personal_next_step: {__noop}, + Permissions.update_checklist_state: {__require_cl_ownership, __require_eng_membership}, + Permissions.create_deployment_target_site: {__require_eng_membership}, + Permissions.star_an_engagement: {__noop}, + Permissions.invite: {__require_eng_membership}, + Permissions.update_account: {__require_eng_membership}, + Permissions.set_ssh: {__require_eng_membership}, + Permissions.update_password: {__require_eng_membership}, + Permissions.delete_vfc: {__require_eng_membership}, + Permissions.get_engagement_status: {__require_eng_membership}, + Permissions.eng_membership: {__noop}, + Permissions.pull_activities: {__require_eng_membership}, + Permissions.export_engagments: {__noop}, + Permissions.update_checklist_decision: {__noop}, + Permissions.remove_from_engagement_team: {__require_eng_membership}, + Permissions.delete_notification: {__is_notification_owner}, + Permissions.change_lab_entry: {__require_eng_membership}, + } + + ###################### + # ADMIN Permissions # + ###################### + ###################################################### + # TODO: We need to decide exactly what are the ADMIN + # TODO: permissions. Currently it matches EL + + # TODO: admin_approve_checklist + ###################################################### + admin_permissions = dict(el_permissions) # Duplicate permissions of EL + admin_permissions.update( # Add Extra permissions to admin + { + Permissions.admin_approve_checklist: {__require_cl_ownership}, + Permissions.remove_from_engagement_team: {__require_eng_membership}, + Permissions.view_checklist_template: {__noop}, + Permissions.edit_checklist_template: {__noop}, + Permissions.archive_engagement: {__noop}, + Permissions.get_el_list: {__noop}, + Permissions.update_engagement_reviewers: {__noop}, + Permissions.edit_nextstep: {__noop}, + Permissions.delete_nextstep: {__noop}, + Permissions.order_nextstep: {__noop}, + Permissions.set_nextstep: {__noop}, + Permissions.edit_stage: {__noop}, + Permissions.edit_progress_bar: {__noop}, + Permissions.get_progress_bar: {__noop}, + Permissions.change_lab_entry: {__noop}, + } + ) + + ###################### + # ADMIN Read only Permissions # + ###################### + admin_ro_permissions = dict() + admin_ro_permissions.update( # Add Extra permissions to admin_ro + { + Permissions.add_vf: {__prevent}, + Permissions.add_feedback: {__noop}, + Permissions.get_vfc: {__noop}, + Permissions.get_engagement_status: {__noop}, + Permissions.eng_membership: {__noop}, + Permissions.pull_activities: {__noop}, + Permissions.star_an_engagement: {__noop}, + Permissions.export_engagments: {__noop}, + } + ) + + def __init__(self): + self.role_standard_user = self.role_el = self.role_admin = self.role_admin_ro = None + self.__load_roles_from_db() + + def check_permissions(self, user, action, eng_uuid, role, eng, cl): + # Retrieve the permission checks that should be performed on this user + # role and action + perm_checks = self.__get_role_checks(user, action) + if not perm_checks: + # Permission Checks were not found, it means that the action is not listed in the permitted + # actions for the role of the user + ret = False, 'Role ' + str(role.name) + ' is not permitted to ' + \ + str(action.name) + '/ Engagement: ' + \ + str(eng_uuid) + " isn't valid" + else: + # Start invoking permissions checks one by one. + for check in perm_checks: + ret = result, message = check( + self, user, action, eng=eng, cl=cl) + if result: + # Permission check succeeded + continue + else: + break # Permission check failed + + return ret + + """ + Determines whether a user is able to perform some action. + """ + + def is_user_able_to(self, user, action, eng_uuid, checklist_uuid): + role = user.role + ret = True, 'OK' + + checklist_uuid = request_data_mgr.get_cl_uuid() + + # Retrieve Engagement and Checklist if their UUIDs were supplied + eng, cl = self.__get_objects_from_db(eng_uuid, checklist_uuid) + if eng and not eng_uuid: + eng_uuid = eng.uuid + + ret = self.check_permissions(user, action, eng_uuid, role, eng, cl) + + return ret + + def __get_objects_from_db(self, eng_uuid, cl_uuid): + eng = cl = None + + try: + if eng_uuid: + eng = Engagement.objects.get(uuid=eng_uuid) + except Engagement.DoesNotExist: + logger.error( + 'ENG was not found while checking permissions... returning 500') + return None, None + + try: + if cl_uuid: + cl = Checklist.objects.get(uuid=cl_uuid) + if not eng: + eng = cl.engagement + except Checklist.DoesNotExist: + logger.error('CL was not found while checking permissions') + cl = None + + return eng, cl + + def __load_roles_from_db(self): + self.role_standard_user, created = Role.objects.get_or_create( + name=Roles.standard_user.name) # @UndefinedVariable + self.role_el, created = Role.objects.get_or_create( + name=Roles.el.name) # @UndefinedVariable + self.role_admin, created = Role.objects.get_or_create( + name=Roles.admin.name) # @UndefinedVariable + self.role_admin_ro, created = Role.objects.get_or_create( + name=Roles.admin_ro.name) # @UndefinedVariable + + def prepare_data_for_auth(self, *args, **kwargs): + eng_uuid = None + # Extract ENG_UUID # + if 'eng_uuid' in kwargs: + eng_uuid = kwargs['eng_uuid'] + elif 'engagement_uuid' in kwargs: + eng_uuid = kwargs['engagement_uuid'] + else: + # Extract eng_uuid from request body + for arg in args: + if eng_uuid != None: + break + if isinstance(arg, rest_framework.request.Request): + try: + if arg.body: + data = json.loads(arg.body) + try: + iter(data) + for item in data: + if 'eng_uuid' in item and item['eng_uuid']: + eng_uuid = item['eng_uuid'] + break + elif 'eng_uuid' in item and item.eng_uuid: + eng_uuid = item.eng_uuid + break + elif item == 'eng_uuid': + eng_uuid = item + break + except TypeError: + if 'eng_uuid' in data and data['eng_uuid']: + eng_uuid = data['eng_uuid'] + + elif 'engagement_uuid' in data and data['engagement_uuid']: + eng_uuid = data['engagement_uuid'] + except Exception as e: + print(e) + pass + + request_data_mgr.set_eng_uuid(eng_uuid) + + # Extract CHECKLIST_UUID # + if 'checklistUuid' in kwargs: + request_data_mgr.set_cl_uuid(kwargs['checklistUuid']) + if (eng_uuid == None): + try: + eng_uuid = Checklist.objects.get( + uuid=request_data_mgr.get_cl_uuid()).engagement.uuid + request_data_mgr.set_eng_uuid(eng_uuid) + except Checklist.DoesNotExist: + raise Exception("auth service couldn't fetch Checklist by checklist uuid=" + + request_data_mgr.get_cl_uuid()) + except Exception as e: + raise Exception( + "Failed fetching engagement uuid from checklist " + request_data_mgr.get_cl_uuid()) + + # Extract engagement by NEXTSTEP_UUID # + if 'ns_uuid' in kwargs: + request_data_mgr.set_ns_uuid(kwargs['ns_uuid']) + if (eng_uuid == None): + next_step = None + try: + next_step = NextStep.objects.get( + uuid=request_data_mgr.get_ns_uuid()) + except NextStep.DoesNotExist: + raise Exception("auth service couldn't fetch NextStep by nextstep uuid=" + + request_data_mgr.get_ns_uuid()) + + try: + eng_uuid = next_step.engagement.uuid + request_data_mgr.set_eng_uuid(eng_uuid) + except: + # If we've gotten here it means that the next_step doesn't have attached + # engagement (e.g personal next_step) + pass + + # Extract engagement by VFC + if ('uuid' in kwargs): + from engagementmanager.rest.vfc import VFCRest + if (isinstance(args[0], VFCRest) == True): + try: + vfc = VFC.objects.get(uuid=kwargs['uuid']) + if (eng_uuid == None): + eng_uuid = vfc.vf.engagement.uuid + request_data_mgr.set_eng_uuid(eng_uuid) + except VFC.DoesNotExist: + raise Exception( + "auth service couldn't fetch vfc by vfc uuid=" + kwargs['uuid']) + + # Extract engagement by VF (unfortunately the url exposed by the server + # get uuid as a parameter and serve both vf and vfc APIs) # + if 'vf_uuid' in kwargs and eng_uuid == None: + try: + eng_uuid = VF.objects.get( + uuid=kwargs['vf_uuid']).engagement.uuid + request_data_mgr.set_eng_uuid(eng_uuid) + except VF.DoesNotExist: + logger.error( + "Prepare_data_for_auth: Couldn't fetch engagement object from VF, trying to fetch from VFC...") + vfc = None + try: + vfc = VFC.objects.get(uuid=kwargs['vf_uuid']) + if (vfc != None): + eng_uuid = vfc.vf.engagement.uuid + request_data_mgr.set_eng_uuid(eng_uuid) + except VFC.DoesNotExist: + logger.error( + "Prepare_data_for_auth: Couldn't fetch engagement object from VFC") + + # Extract engagement by ChecklistDecision + if 'decision_uuid' in kwargs and eng_uuid == None: + try: + eng_uuid = ChecklistDecision.objects.get( + uuid=kwargs['decision_uuid']).checklist.engagement.uuid + request_data_mgr.set_eng_uuid(eng_uuid) + except ChecklistDecision.DoesNotExist: + logger.error( + "Prepare_data_for_auth: Couldn't fetch engagement object from ChecklistDecision") + + # Extract notification uuid for permission check + if 'notif_uuid' in kwargs: + request_data_mgr.set_notification_uuid(kwargs['notif_uuid']) + + return eng_uuid diff --git a/django/engagementmanager/service/base_service.py b/django/engagementmanager/service/base_service.py new file mode 100755 index 0000000..93e48f8 --- /dev/null +++ b/django/engagementmanager/service/base_service.py @@ -0,0 +1,52 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from abc import ABCMeta +from engagementmanager.git.git_manager import GitManager +from engagementmanager.service.logging_service import LoggingServiceFactory + + +class BaseSvc(): + ''' + classdocs This is the base abstract class of all ice Services delegated from the Rest layer + ''' + __metaclass__ = ABCMeta + + logger = LoggingServiceFactory.get_logger() + + gitManager = GitManager() diff --git a/django/engagementmanager/service/bus_service.py b/django/engagementmanager/service/bus_service.py new file mode 100755 index 0000000..5096fbb --- /dev/null +++ b/django/engagementmanager/service/bus_service.py @@ -0,0 +1,75 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.bus.handlers.service_bus_base_handler import ServiceBusBaseHandler + +from engagementmanager.utils.vvp_exceptions import VvpGeneralException + + +class BusService: + handlers_pairs = [] + + def __init__(self): + pass + + def register(self, handler, message_type): + if not isinstance(handler, ServiceBusBaseHandler): + raise VvpGeneralException("You can't register handler which is not from type of ServiceBusBaseHandler") + + handler_pair = self.__get_or_create_handler_pair(message_type) + handler_pair["handlers"].append(handler) + + def send_message(self, message): + handler_pair = self.__get_or_create_handler_pair(type(message)) + + for handler in handler_pair["handlers"]: + handler.validate_message(message) + handler.handle_message(message) + + def __get_or_create_handler_pair(self, message_type): + result = None + for handler_pair in self.handlers_pairs: + if handler_pair["type"] == message_type: + result = handler_pair + break + + if result is None: + result = {"type": message_type, "handlers": []} + self.handlers_pairs.append(result) + + return result diff --git a/django/engagementmanager/service/checklist_audit_log_service.py b/django/engagementmanager/service/checklist_audit_log_service.py new file mode 100755 index 0000000..f726950 --- /dev/null +++ b/django/engagementmanager/service/checklist_audit_log_service.py @@ -0,0 +1,105 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from engagementmanager.models import ChecklistDecision, ChecklistAuditLog, Checklist +from engagementmanager.serializers import ThinChecklistAuditLogModelSerializer +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def addAuditLogToDecision(decision, description, user, category=''): + """ + expected: decisionUuid(string), description(string), user(object), category is optional(string) + result: new auditlog object would be create and attached to a decision object. + """ + audit = ChecklistAuditLog.objects.create(decision=decision, + description=description, category=category, creator=user) + auditData = ThinChecklistAuditLogModelSerializer(audit).data + return auditData + + +def getAuditLogsWithDecision(decisionUuid, user): + """ + expected: decisionUuid(string), user(object) + result: all audit logs objects that attached to a decision would be returned in a json. + """ + data = dict() + if checklistUuid == '' or not user: # @UndefinedVariable + msg = "checklistUuid or user == None" + logger.error(msg) + msg = "AuditLogs were not retrieved due to bad parameters" + raise KeyError(msg) + + decision = ChecklistDecision.objects.get(uuid=decisionUuid) + audits = ChecklistAuditLog.objects.filter(decision=decision) + data['audits'] = ThinChecklistAuditLogModelSerializer(audits, many=True).data + auditsData = json.dumps(data, ensure_ascii=False) + return auditsData + + +def addAuditLogToChecklist(checklist, description, user, category=''): + """ + expected: checklistUuid(string), description(string), user(object), category is optional(string) + result: new auditlog object would be create and attached to a checklist object. + """ + audit = ChecklistAuditLog.objects.create(checklist=checklist, + description=description, category=category, creator=user) + auditData = ThinChecklistAuditLogModelSerializer(audit).data + logger.debug("audit log was successfully updated") + return auditData + + +def getAuditLogsWithChecklist(checklistUuid, user): + """ + expected: checklistUuid(string), user(object) + result: all audit logs objects that attached to a checklist would be returned in a json. + """ + data = dict() + if checklistUuid == '' or not user: # @UndefinedVariable + msg = "checklistUuid or user == None" + logger.error(msg) + msg = "AuditLogs were not retrieved due to bad parameters" + raise KeyError(msg) + + checklist = Checklist.objects.get(uuid=checklistUuid) + audits = ChecklistAuditLog.objects.filter(checklist=checklist) + data['audits'] = ThinChecklistAuditLogModelSerializer(audits, many=True).data + auditsData = json.dumps(data, ensure_ascii=False) + return auditsData diff --git a/django/engagementmanager/service/checklist_decision_service.py b/django/engagementmanager/service/checklist_decision_service.py new file mode 100755 index 0000000..e94c059 --- /dev/null +++ b/django/engagementmanager/service/checklist_decision_service.py @@ -0,0 +1,122 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from django.core.exceptions import PermissionDenied +from rest_framework.exceptions import MethodNotAllowed +from engagementmanager.models import ChecklistDecision +from engagementmanager.serializers import ThinChecklistDecisionModelSerializer +from engagementmanager.utils.constants import CheckListState, \ + CheckListDecisionValue, Roles +from engagementmanager.utils.validator import logEncoding +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def setDecision(decisionUuid, user, value): + logger.debug("attempting setDecision(user=%r, value=%r)...", user, value) + + if not decisionUuid or not user or value not in CheckListDecisionValue.__members__: + msg = "decisionUuid or value are empty or invalid / user == None" + logger.error(msg) + msg = "decision wasn't change due to bad parameters" + raise KeyError(msg) + + decision = ChecklistDecision.objects.get(uuid=decisionUuid) + checklist = decision.checklist + + # @UndefinedVariable + if (checklist.owner.email == user.email and user.role.name == Roles.el.name) or (user.role.name == Roles.admin.name): + if checklist.state == CheckListState.review.name: # @UndefinedVariable + if decision.review_value != value: + decision.review_value = value + decision.save() + msg = "review_value was successfully changed for decision: " + decision.uuid + " , value: " + value + else: + msg = "review_value was already the same: " + decision.uuid + " , value: " + value + logger.debug(msg) + elif checklist.state == CheckListState.peer_review.name: # @UndefinedVariable + if decision.peer_review_value != value: + decision.peer_review_value = value + decision.save() + msg = "peer_review_value was successfully changed for decision: " + decision.uuid + " , value: " + value + else: + msg = "review_value was already the same: " + decision.uuid + " , value: " + value + logger.debug(msg) + elif checklist.state == CheckListState.automation.name: # @UndefinedVariable + if decision.review_value != value: + decision.peer_review_value = value + decision.save() + msg = "peer_review_value was successfully changed for decision: " + decision.uuid + " , value: " + value + else: + msg = "review_value was already the same: " + decision.uuid + " , value: " + value + + if decision.review_value != value: + decision.review_value = value + decision.save() + msg = "review_value was successfully changed for decision: " + decision.uuid + " , value: " + value + else: + msg = "review_value was already the same: " + decision.uuid + " , value: " + value + logger.debug(msg) + else: + msg = "checklist's state is an invalid state for the decision change and should be different" + logger.error(msg) + msg = "decision wasn't change, Checklist's state is not allowed to change the decision" + raise MethodNotAllowed(msg) + return msg + else: + msg = "user isn't an EL / The User (" + user.full_name + \ + ") tried to change the decision while the current owner is " + checklist.owner.full_name + logger.error(logEncoding(msg)) + msg = "Action is forbidden" + raise PermissionDenied(msg) + + +def getDecision(decisionUuid, user): + data = dict() + if decisionUuid == '' or (not user and user.role.name == Roles.el.name): # @UndefinedVariable + msg = "decisionUuid or (user == None / user.role != EL)" + logger.error(msg) + msg = "decision wasn't retrieved due to bad parameters / you are not authorized" + raise KeyError(msg) + + decision = ChecklistDecision.objects.get(uuid=decisionUuid) + data['decision'] = ThinChecklistDecisionModelSerializer(decision, many=False).data + decisionData = json.dumps(data, ensure_ascii=False) + return decisionData diff --git a/django/engagementmanager/service/checklist_service.py b/django/engagementmanager/service/checklist_service.py new file mode 100755 index 0000000..0df7edd --- /dev/null +++ b/django/engagementmanager/service/checklist_service.py @@ -0,0 +1,509 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Q +from django.db.models.aggregates import Max +from engagementmanager.apps import bus_service +from engagementmanager.bus.messages.activity_event_message import \ + ActivityEventMessage +from engagementmanager.git.git_manager import GitManager +from engagementmanager.models import ChecklistTemplate, Checklist, Engagement, \ + ChecklistAuditLog, ChecklistDecision, ChecklistLineItem, IceUserProfile, VF, \ + ChecklistSection, Role +from engagementmanager.serializers import ThinChecklistModelSerializer, \ + ThinChecklistAuditLogModelSerializer, ThinChecklistDecisionModelSerializer, \ + ThinPostChecklistResponseModelSerializer, ChecklistTemplateModelSerializer, \ + ChecklistSectionModelSerializer, ChecklistLineItemModelSerializer +from engagementmanager.service.checklist_audit_log_service import \ + addAuditLogToDecision, addAuditLogToChecklist +from engagementmanager.service.checklist_decision_service import setDecision +from engagementmanager.service.checklist_state_service import set_state +from engagementmanager.service.base_service import BaseSvc +from engagementmanager.utils.constants import Roles, CheckListState, \ + CheckListLineType +from engagementmanager.utils.activities_data import TestFinishedActivityData +from engagementmanager.utils.vvp_exceptions import VvpObjectNotAvailable +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.utils.validator import logEncoding +from engagementmanager.vm_integration.vm_client import \ + send_jenkins_job_and_gitlab_repo_exists, executor +from validationmanager.em_integration.vm_api import get_jenkins_build_log +import json +import time +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class CheckListSvc(BaseSvc): + def retreive_cl_files_for_engagment(self, eng_uuid): + vf_associated_files_list = [] + + checklists_of_eng = Checklist.objects.filter(engagement__uuid=eng_uuid).exclude( + state=CheckListState.archive.name).exclude(state=CheckListState.closed.name) # @UndefinedVariable + + for checklistObj in checklists_of_eng: + associated_files = json.loads(checklistObj.associated_files) + vf_associated_files_list = vf_associated_files_list + associated_files + return vf_associated_files_list + + def getDataForCreateNewChecklist(self, user, eng_uuid): + engagement = Engagement.objects.get(uuid=eng_uuid) + vf = engagement.vf + + if not send_jenkins_job_and_gitlab_repo_exists(vf): + msg = "Jenkins job or gitlab repo is still missing" + logger.error(msg) + return False + + # Get all templates + data = self.getChecklistTemplates() + + data['checkListAssociatedFiles'] = self.gitManager.getRepoAssociatedFilesForUser( + eng_uuid) + return data + + def getChecklistTemplates(self, templateUuid=None): + """Return checklist template with nested sections and their nested line items""" + data = dict() + if not templateUuid: + checkListTemplates = ChecklistTemplate.objects.all() + if (checkListTemplates): + data['checkListTemplates'] = ChecklistTemplateModelSerializer( + checkListTemplates, many=True).data + return data + cl_template = ChecklistTemplate.objects.get(uuid=templateUuid) + if (cl_template != None): + data = ChecklistTemplateModelSerializer( + cl_template, many=False).data + sections = ChecklistSection.objects.filter(template=cl_template) + if (sections != None): + section_list = [] + for sec in sections: + section_data = dict() + section_data = ChecklistSectionModelSerializer( + sec, many=False).data + + lineItems = ChecklistLineItem.objects.filter(section=sec) + section_data['lineItems'] = ChecklistLineItemModelSerializer( + lineItems, many=True).data + section_list.append(section_data) + + data['sections'] = section_list + + return data + + def createNewSection(self, section, templateObj): + """Create new section for a given template """ + logger.debug( + "Creating a new section. Section name = " + section['name']) + + weight = int(ChecklistSection.objects.filter(template=templateObj).aggregate( + max_weight=Max('weight'))['max_weight'] or 0) + 1 + + newSection = ChecklistSection.objects.create( + name=section.get('name', None), + description=section.get('description', None), + validation_instructions=section.get( + 'validation_instructions', None), + template=templateObj, + weight=weight) + + return newSection + + def createNewLineItemForSection(self, newSectionObj, listItem, templateObj): + """Create new line item for a given section and template """ + + weight = int(ChecklistLineItem.objects.filter(section=newSectionObj).aggregate( + max_weight=Max('weight'))['max_weight'] or 0) + 1 + + ChecklistLineItem.objects.create( + name=listItem['name'], + description=listItem.get('description', None), + # @UndefinedVariable + line_type=listItem.get('line_type', CheckListLineType.auto.name), + validation_instructions=listItem.get( + 'validation_instructions', None), + section=newSectionObj, + template=templateObj, + weight=weight) + + def delete(self, dict_structure, query_set, entity, isDirty): + """Generically find the xor result of the user input and the db data. Assumption: If entities exits in DB but not in user input they'll be deleted""" + uuid_client = [dict['uuid'] for dict in dict_structure] + uuid_db = [record.uuid for record in query_set] + uuids_to_delete = set(uuid_db) - set(uuid_client) + for u_uid in uuids_to_delete: + entity.objects.filter(uuid=u_uid).delete() + # Note: No need to delete ChecklistLineItem corresponding to this section + # since there is a CASCADE operation on delete section + isDirty[0] = True + + def editIfChanged(self, entity, uidict, fieldList): + """Generic function to check that set of fields are modified on a certain entity""" + isChanged = False + for field in fieldList: + if (field in uidict): + if (isChanged != True and entity.__dict__[field] == uidict[field]): + isChanged = False + else: + entity.__dict__[field] = uidict[field] + isChanged = True + return isChanged + + def updateTemplateFields(self, clTemplate, checklistTemplate, isDirty): + if (self.editIfChanged(clTemplate, checklistTemplate, ['name'])): + clTemplate.save() + isDirty[0] = True + + def updateSectionFields(self, section, sec, isDirty): + if (self.editIfChanged(section, sec, ['name'])): + section.save() + isDirty[0] = True + + def updateLineItemFields(self, lineitem, li, isDirty): + if (self.editIfChanged(lineitem, li, ['name', 'description', 'validation_instructions', 'line_type'])): + lineitem.save() + isDirty[0] = True + + def editChecklistTemplate(self, checklistTemplate): + """edit the template+section+line-item of user input""" + NEW_ENTITY = "newEntity" # this is an indication on top of the provided json to create the entity + templateObj = None + isDirty = [False] + if ('uuid' in checklistTemplate): + templateUuid = checklistTemplate['uuid'] + templateObj = ChecklistTemplate.objects.get(uuid=templateUuid) + self.updateTemplateFields(templateObj, checklistTemplate, isDirty) + # SECTIONS + if ('sections' in checklistTemplate): + sections = checklistTemplate['sections'] + query_set = templateObj.checklistsection_set.all() + self.delete(sections, query_set, ChecklistSection, isDirty) + sectionObj = None + for sec in sections: + if (sec['uuid'] == NEW_ENTITY): + sectionObj = self.createNewSection(sec, templateObj) + isDirty[0] = True + else: # section was only updated + sectionObj = ChecklistSection.objects.get( + uuid=sec['uuid']) + self.updateSectionFields(sectionObj, sec, isDirty) + # LINE-ITEMS + if ('lineItems' in sec): + lineItems = sec['lineItems'] + query_set = sectionObj.checklistlineitem_set.all() + self.delete(lineItems, query_set, + ChecklistLineItem, isDirty) + for li in lineItems: + if (li['uuid'] == NEW_ENTITY): + self.createNewLineItemForSection( + sectionObj, li, templateObj) + isDirty[0] = True + else: # line-item was only updated + lineitem = ChecklistLineItem.objects.get( + uuid=li['uuid']) + self.updateLineItemFields(lineitem, li, isDirty) + + executor.submit(self.decline_all_template_checklists, + isDirty[0], templateObj, request_data_mgr.get_user()) + + def decline_all_template_checklists(self, isDirty, templateObj, user): + request_data_mgr.set_user(user) + checklists = None + + start = time.clock() + try: + if (isDirty == True): + states_to_exclude = [CheckListState.archive.name, CheckListState.closed.name, + CheckListState.pending.name] # @UndefinedVariable + checklists = Checklist.objects.filter( + template=templateObj).exclude(state__in=states_to_exclude) + logger.debug("Number of checklists=" + + str(len(checklists))) + for checklist in checklists: + request_data_mgr.set_cl_uuid(checklist.uuid) + request_data_mgr.set_eng_uuid(checklist.engagement.uuid) + set_state( + True, # means that the checklist will be declined and a cloned one is created in PENDING status + checklist.uuid, + isMoveToAutomation=True, + description="""Checklist {name} was rejected since its template ({template}) was edited/deleted""".format( + name=checklist.name, template=templateObj.name), # means the checklist will be triggered into automation cycle + ) + except Exception as e: + msg = """Something went wrong while trying to reject check-lists which its template was changed. template={template}. Error:""".format( + template=templateObj.name) + logger.error(msg + " " + str(e)) + raise e # Don't remove try-except, it supports async invocation + end = time.clock() + logger.debug("TIME:" + str(end - start)) + + def getChecklist(self, user, checklistUuid): + + data = dict() + checklist = None + + if user.role.name == Roles.admin.name or user.role.name == Roles.admin_ro.name: # @UndefinedVariable + checklist = Checklist.objects.get(uuid=checklistUuid) + else: + checklist = Checklist.objects.get( + Q(uuid=checklistUuid), Q(creator=user) | Q(owner=user)) + + # CheckList + if checklist.state == CheckListState.archive.name: # @UndefinedVariable + msg = "got a request for a checklist which is an archived one, might have been due to an admin edit of a checklist template." + logger.error(msg) + msg = "Requested checklist is archived, reloading checklists list" + raise VvpObjectNotAvailable(msg) + data['checklist'] = ThinChecklistModelSerializer( + checklist, many=False).data + vf = VF.objects.get(engagement=checklist.engagement) + data['checklist']['associated_files'] = json.loads( + data['checklist']['associated_files']) + data['checklist']['jenkins_log'] = get_jenkins_build_log( + vf, checklistUuid) + data['checklist']['repo_associated_files'] = GitManager( + ).getRepoAssociatedFilesForUser(checklist.engagement.uuid) + # CheckList Audit Logs + # here all fetched records should have decision==null + checklistAuditLogs = ChecklistAuditLog.objects.filter( + checklist__uuid=checklistUuid) + serializedAuditLogsData = ThinChecklistAuditLogModelSerializer( + checklistAuditLogs, many=True).data + data['checklistAuditLogs'] = serializedAuditLogsData + + # CheckList Decisions + LineItems + Sections (The data is nested thanks + # to the serializer) + checklistDecisions = ChecklistDecision.objects.filter( + checklist__uuid=checklistUuid) + serializedDecisionsData = ThinChecklistDecisionModelSerializer( + checklistDecisions, many=True).data + checklistLineItems = {} + for checklistDecision in serializedDecisionsData: + section_uuid = checklistDecision['lineitem']['section']['uuid'] + section_weight = checklistDecision['lineitem']['section']['weight'] + section_key = str(section_weight) + "_" + section_uuid + if section_key not in checklistLineItems: + checklistLineItems[section_key] = {} + checklistLineItems[section_key]['section'] = checklistDecision['lineitem']['section'] + checklistLineItems[section_key]['decisions'] = {} + checklistLineItems[section_key]['weight'] = section_weight + + decision_uuid = checklistDecision['uuid'] + line_item_weight = checklistDecision['lineitem']['weight'] + decision_key = str(line_item_weight) + "_" + decision_uuid + checklistLineItems[section_key]['decisions'][decision_key] = checklistDecision + checklistLineItems[section_key]['decisions'][decision_key]['weight'] = line_item_weight + + data['checklistDecisions'] = checklistLineItems + + # Decision Audit Logs + data['decisionAuditLogs'] = {} + for checklistDecision in checklistDecisions: + # here all fetched records should have checklist==null + decisionAuditLogs = ChecklistAuditLog.objects.filter( + decision=checklistDecision) + if decisionAuditLogs.count() > 0: + serializedAuditLogsData = ThinChecklistAuditLogModelSerializer( + decisionAuditLogs, many=True).data + data['decisionAuditLogs'][checklistDecision.uuid] = serializedAuditLogsData + + logger.debug("get existing checklist has succeeded for checklist.uuid=" + str(checklist.uuid) + + ", user.uuid=" + str(user.uuid) + ", checklist.uuid=" + str(checklistUuid)) + + return data + + def getEngagementFiles(self, eng_uuid): + repo_files = self.gitManager.getRepoAssociatedFilesForUser(eng_uuid) + return repo_files + + def createOrUpdateChecklist(self, checkListName, checkListTemplateUuid, checkListAssociatedFiles, checklistUuid=None): + template = None + checklist = None + user = request_data_mgr.get_user() + eng_uuid = request_data_mgr.get_eng_uuid() + + vf = VF.objects.get(engagement__uuid=eng_uuid) + + if not send_jenkins_job_and_gitlab_repo_exists(vf): + msg = "Jenkins job or gitlab repo is still missing" + logger.error(msg) + msg = "Create or update checklist is not ready yet" + raise Exception(msg) + + # associated_files may be delivered in this format + # [{"File": "bar"}, {"File": "baz"}, {"File": "foo"}, {"File": "quux"}] + # but we want to store it in this format + # ["bar", "baz", "foo", "quux"] + + repo_files = self.gitManager.getRepoAssociatedFilesForUser(eng_uuid) +# checklist_files_list = [f['File'] if isinstance(f, dict) else f for f in checkListAssociatedFiles] + checklist_files_list = [] + for file in checkListAssociatedFiles: + if isinstance(file, dict): + checklist_files_list.append(file['File']) + else: + checklist_files_list.append(file) + for added_name in checklist_files_list: + if added_name not in repo_files: + logger.error("Update checklist has failed. " + + added_name + " doesnt exist in repo") + msg = "Failed to create checklist, please select valid file" + raise ValueError(msg) + + associated_files = json.dumps(checklist_files_list, ensure_ascii=False) + + engagement = Engagement.objects.get(uuid=eng_uuid) + template = ChecklistTemplate.objects.get(uuid=checkListTemplateUuid) + + if (checklistUuid != None): # Update Checklist + checklist = Checklist.objects.get(uuid=checklistUuid) + checklist.name = checkListName + checklist.associated_files = associated_files + checklist.template = template + checklist.save() + + if (associated_files != None and len(checklist_files_list) > 0): + set_state( + decline=True, + description="Checklist: " + checklist.name + + "in Pending state will transition to Automation because it has associated files", + isMoveToAutomation=True, # means the checklist will be triggered into automation cycle + checklist_uuid=checklist.uuid + ) + else: # create ChcekList + if (user.role.name == Roles.admin.name): # @UndefinedVariable + incharge_personal = engagement.reviewer + else: + incharge_personal = user + vf = None + vf = VF.objects.get(engagement=engagement) + + if (vf.git_repo_url == None): + msg = "Can't create checklist since the attached VF (" + \ + vf.name + ") doesn't contain git_repo_url" + logger.error( + "Update checklist has failed. " + logEncoding(msg)) + raise ObjectDoesNotExist(msg) + + checklist = Checklist(name=checkListName, validation_cycle=1, associated_files=associated_files, + state=CheckListState.pending.name, engagement=engagement, template=template, creator=user, owner=incharge_personal) # @UndefinedVariable + line_items_list = ChecklistLineItem.objects.filter( + template=template) + checklist.save() + for lineitem in line_items_list: + new_decision = ChecklistDecision(checklist=checklist, + template=template, lineitem=lineitem) + new_decision.save() + + # When Checklist is created with files move it it automation + if (associated_files != None and len(checklist_files_list) > 0): + set_state( + decline=False, + checklist_uuid=checklist.uuid, + description="Checklist: " + checklist.name + + "in Pending state will transition to Automation because it has associated files", + isMoveToAutomation=True # means the checklist will be triggered into automation cycle + ) + + logger.debug( + "Create/Update checklist has succeeded for checklist.uuid=" + str(checklist.uuid)) + + return ThinPostChecklistResponseModelSerializer(checklist).data + + def deleteChecklist(self, checklist_uuid): + checklist = Checklist.objects.get(uuid=checklist_uuid) + checklist.delete() + + logger.debug( + "Delete checklist has succeeded for checklist.uuid=" + str(checklist_uuid)) + + def setChecklistDecisionsFromValMgr(self, user, checklist_uuid, decisions, checklist_results_from_jenkins): + checklist = Checklist.objects.get(uuid=checklist_uuid, owner=user, + state=CheckListState.automation.name) # @UndefinedVariable + + logger.debug("setChecklistDecisionsFromValMgr() checklist_uuid=%r, len(decisions)=%d", + checklist_uuid, len(decisions),) + + if ('error' in checklist_results_from_jenkins): + el_role = Role.objects.get(name=Roles.el.name) + admin_role = Role.objects.get(name=Roles.admin.name) + el_admin_list = IceUserProfile.objects.all().filter( + Q(role=el_role) | Q(role=admin_role)) + + activity_data = TestFinishedActivityData( + el_admin_list, checklist.engagement, checklist_results_from_jenkins['error']) + bus_service.send_message(ActivityEventMessage(activity_data)) + + msg = "test_finished signal from Jenkins has arrived with error: {}".format( + checklist_results_from_jenkins['error']) + logger.error(msg) + set_state(True, checklist_uuid, isMoveToAutomation=False, + description=checklist_results_from_jenkins['error']) + raise Exception(msg) + + ChecklistLineItem.objects.filter(template=checklist.template).update( + line_type=CheckListLineType.manual.name) # @UndefinedVariable + + for decision in decisions: + lineitem_obj = ChecklistLineItem.objects.get( + uuid=decision['line_item_id']) + lineitem_obj.line_type = CheckListLineType.auto.name # @UndefinedVariable + lineitem_obj.save() + + decision_obj = ChecklistDecision.objects.get( + checklist=checklist, lineitem=lineitem_obj) + setDecision(decisionUuid=decision_obj.uuid, + user=user, value=decision['value']) + + if (decision['audit_log_text'] != '' and decision['audit_log_text'] != None): + addAuditLogToDecision(decision=decision_obj, + description=decision['audit_log_text'], user=user, category='') + + desc = "The {} validation test suite has completed. The decisions " +\ + "based on the test results have successfully been set in the " +\ + "checklist.".format(checklist.template.category) + addAuditLogToChecklist(checklist=checklist, description=desc, + user=user, category='') + checklistData = ThinChecklistModelSerializer(checklist, many=False).data + set_state(False, checklist.uuid, + isMoveToAutomation=True, description="") + + return checklistData diff --git a/django/engagementmanager/service/checklist_state_service.py b/django/engagementmanager/service/checklist_state_service.py new file mode 100755 index 0000000..1903c47 --- /dev/null +++ b/django/engagementmanager/service/checklist_state_service.py @@ -0,0 +1,434 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.db.models import Q +from django.utils import timezone +from engagementmanager.decorator.auth import auth +from engagementmanager.slack_client.api import SlackClient +from engagementmanager.models import ChecklistDecision, Checklist, \ + IceUserProfile, VF, ChecklistLineItem, ChecklistAuditLog, Role +from engagementmanager.service.authorization_service import Permissions +from engagementmanager.service.checklist_audit_log_service import \ + addAuditLogToChecklist +from engagementmanager.service.engagement_service import \ + update_or_insert_to_recent_engagements, update_eng_validation_details +from engagementmanager.utils.constants import CheckListState, \ + CheckListDecisionValue, Roles, RecentEngagementActionType +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.vm_integration.vm_client import \ + send_cl_from_pending_to_automation_event +from rest_framework.exceptions import MethodNotAllowed +import random +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def insert_to_recent_engagements(owner=None, action=None, vf=None): + if vf == None: + # If VF wasn't supplied let's fetch it using checklist and + # checklist.engagement + checkListObj = Checklist.objects.get( + uuid=request_data_mgr.get_cl_uuid()) + vf = VF.objects.get(engagement=checkListObj.engagement) + + logger.debug("Adding vf " + str(vf.uuid) + + " to recent engagements table for user " + owner.full_name) + update_or_insert_to_recent_engagements( + owner.uuid, vf, action) # @UndefinedVariable + + +def description_creator(checklist, next_state, additional_comment=""): + if additional_comment: + description = "The " + checklist.name + " checklist was changed to the " +\ + next_state.lower() + " state. " + "\n" +\ + additional_comment + else: + description = "The " + checklist.name + " checklist was changed to the " +\ + next_state.lower() + " state." + return description + + +''' + If kwargs['isMoveToAutomation']==True than the CL will not be cloned but reverted to automation, else (False) will be cloned and returned in pending +''' + + +def set_state(decline, checklist_uuid, isMoveToAutomation=True, description=None): + logger.debug('set_state(decline=%r,checklist_uuid=%r,get_request_data_vars= %r)', + decline, checklist_uuid, request_data_mgr.get_request_data_vars()) + + if checklist_uuid != None: # was sent explicitly + request_data_mgr.set_cl_uuid(checklist_uuid) + + if any(x is None for x in [checklist_uuid, request_data_mgr.get_user(), description]): + msg = "checklist uuid or user or description is None" + logger.error(msg) + msg = "checklist state wasn't change due to bad parameters" + raise KeyError(msg) + + additional_comment = description + + checklist = retrieve_checklist_object(checklist_uuid) + + # get metadata for slack notifications + slack_client = SlackClient() + checklist_name = checklist.name + engagement = checklist.engagement + reviewer = engagement.reviewer + peer_reviewer = engagement.peer_reviewer + engagement_manual_id = '' + if engagement is not None: + engagement_manual_id = engagement.engagement_manual_id + + vf = VF.objects.get(engagement__uuid=engagement.uuid) + vf_name = "" + if vf is not None: + vf_name = vf.name + + if not checklist: + msg = "checklist state wasn't change due to bad parameters" + raise KeyError(msg) + + # @UndefinedVariable + if checklist.state == CheckListState.closed.name or checklist.state == CheckListState.archive.name: + msg = "attempt to change state to the next one from 'closed'/'archive', no actions were made." + logger.error(msg) + msg = "checklist's state is already closed/archive, can not move forward in states." + raise FileExistsError(msg) + + elif decline and checklist.state != CheckListState.pending.name: # @UndefinedVariable + logger.debug( + 'set_state: decline and not pending -< about to set the state to ARCHIVE and duplicate the checklist') + set_state_to_archive(isMoveToAutomation, description) + + # @UndefinedVariable + return check_sts(checklist, request_data_mgr.get_user(), CheckListState.archive.name, additional_comment) + + elif checklist.state == CheckListState.pending.name: # @UndefinedVariable + logger.debug('set_state: pending to automation') + set_state_to_automation() + + # @UndefinedVariable + return check_sts(checklist, request_data_mgr.get_user(), CheckListState.automation.name, additional_comment) + + # this case is when getting a signal from VM that jenkins has finished all + # tests + elif checklist.state == CheckListState.automation.name: # @UndefinedVariable + logger.debug('set_state: automation to review') + set_state_to_review(checklist) + slack_client.send_notification_to_reviewer_when_automation_completes( + engagement_manual_id, vf_name, reviewer, checklist_name) + + # @UndefinedVariable + return check_sts(checklist, request_data_mgr.get_user(), CheckListState.review.name, additional_comment) + + elif checklist.state == CheckListState.review.name: # @UndefinedVariable + logger.debug('set_state: review to peer review') + set_state_to_peer_review() + slack_client.send_notification_to_peer_reviewer_when_the_review_completes( + engagement_manual_id, vf_name, reviewer, peer_reviewer, checklist_name) + + # @UndefinedVariable + return check_sts(checklist, request_data_mgr.get_user(), CheckListState.peer_review.name, additional_comment) + + elif checklist.state == CheckListState.peer_review.name: # @UndefinedVariable + logger.debug('set_state: peer review to approval') + set_state_to_approval() + admins = IceUserProfile.objects.filter(role__name=Roles.admin.name) + slack_client.send_notification_to_admins_when_the_peer_review_completes( + engagement_manual_id, vf_name, reviewer, peer_reviewer, admins, checklist_name) + + # @UndefinedVariable + return check_sts(checklist, request_data_mgr.get_user(), CheckListState.approval.name, additional_comment) + + elif checklist.state == CheckListState.approval.name: # @UndefinedVariable + logger.debug('set_state: approval to handoff') + set_state_to_handoff() + slack_client.send_notification_to_reviewer_when_approved( + engagement_manual_id, vf_name, reviewer, checklist_name) + + # @UndefinedVariable + return check_sts(checklist, request_data_mgr.get_user(), CheckListState.handoff.name, additional_comment) + + elif checklist.state == CheckListState.handoff.name: # @UndefinedVariable + logger.debug('set_state: handoff to closed') + set_state_to_closed() + admins = IceUserProfile.objects.filter(role__name=Roles.admin.name) + slack_client.send_notifications_when_closed( + engagement_manual_id, vf_name, reviewer, peer_reviewer, admins, checklist_name) + + # @UndefinedVariable + return check_sts(checklist, request_data_mgr.get_user(), CheckListState.closed.name, additional_comment) + + +def duplicate_checklist_and_its_auditlogs(checklist, isMoveToAutomation): + ''' Create the basic duplicated checklist object based on the original one ''' + + newState = CheckListState.pending.name # @UndefinedVariable + checklistDupObject = Checklist.objects.create( + name=checklist.name, + validation_cycle=checklist.validation_cycle + 1, + associated_files=checklist.associated_files, + engagement=checklist.engagement, + template=checklist.template, + creator=checklist.creator, + owner=checklist.creator, + state=newState) + + ''' Fetch all original cl audit logs and attach it to the duplicated one ''' + audits = ChecklistAuditLog.objects.filter(checklist=checklist) + for item in audits: + audit = addAuditLogToChecklist( + checklistDupObject, item.description, item.creator) + + if not audit: + logger.error( + "duplicate_checklist_and_its_auditlogs: Failed to create a duplicated audit log in the DB") + msg = "checklist state wasn't change" + raise Exception(msg) + + ''' Fetch all original line items and attach it to the duplicated one ''' + line_items_list = ChecklistLineItem.objects.filter( + template=checklist.template) + # Implementation is based on space and performance aspect and not particularly one of them + #(could have just change the internal object's cl field to the new object and reset their values) + for lineitem in line_items_list: + old_decisions = ChecklistDecision.objects.filter( + lineitem=lineitem, checklist=checklist, template=checklist.template) + if len(old_decisions) == 0: + new_decision = ChecklistDecision.objects.create( + checklist=checklistDupObject, template=checklistDupObject.template, lineitem=lineitem) + else: + for decision in old_decisions: + new_decision = ChecklistDecision.objects.create( + checklist=checklistDupObject, template=checklist.template, lineitem=lineitem) + old_decision_auditlogs = ChecklistAuditLog.objects.filter( + decision=decision) + for audit in old_decision_auditlogs: + audit = ChecklistAuditLog.objects.create( + decision=new_decision, description=audit.description, category='', creator=audit.creator) + + if isMoveToAutomation == True: # This is a scenario in which we send to VM cl_from_pending_to_automation_event + logger.debug("Cloned Checklist is triggered as to automation") + try: + set_state_to_automation(checklistDupObject) + except KeyError: + # delete new checklist since we don't want duplicate checklist while + # the other one is still not archived + checklistDupObject.delete() + + return checklistDupObject + + +def check_sts(checklist, user, next_state, additional_comment): + description = description_creator( + checklist, next_state, additional_comment=additional_comment) # @UndefinedVariable + if not description: + msg = "failed to set the state to the next one due to invalid parameters." + raise ValueError(msg) + addAuditLogToChecklist(checklist, description, user) + return checklist + + +def check_decision_meet_criterias(checkListObj, review_type): + if not type: + return True + + if review_type == 'review_value': + invalid_decisions = ChecklistDecision.objects.filter(Q(checklist=checkListObj) & + ( + Q(review_value=CheckListDecisionValue.na.name) + | Q(review_value=CheckListDecisionValue.denied.name) + )).count() # @UndefinedVariable + elif review_type == 'peer_review_value': + invalid_decisions = ChecklistDecision.objects.filter(Q(checklist=checkListObj) & + ( + Q(peer_review_value=CheckListDecisionValue.na.name) | + Q(peer_review_value=CheckListDecisionValue.denied.name) + )).count() # @UndefinedVariable + else: + return True + + if invalid_decisions: + msg = "checklist state wasn't change, not all decisions are approved / na" + raise MethodNotAllowed(msg) + + +def retrieve_checklist_and_its_decisions(cluuid, review_type): + checkListObj = retrieve_checklist_object(cluuid) + if not checkListObj: + msg = "checklist state wasn't change" + raise KeyError(msg) + check_decision_meet_criterias(checkListObj, review_type) + return checkListObj + + +def retrieve_checklist_object(cluuid): + checklist = Checklist.objects.get(uuid=cluuid) + return checklist + + +""" +This method is called when an EL / Peer Reviewer declines a CL or creates a Next step for them after declining a specific line item in the CL. +""" + + +@auth(Permissions.set_checklist_decision, is_internal=True) +def set_state_to_archive(isMoveToAutomation=True, description=None): + checkListObj = retrieve_checklist_and_its_decisions( + request_data_mgr.get_cl_uuid(), '') # @UndefinedVariable + + rejection_description = description_creator( + checkListObj, CheckListState.archive.name, description) # @UndefinedVariable + addAuditLogToChecklist( + checkListObj, rejection_description, request_data_mgr.get_user()) + checklistDupObject = duplicate_checklist_and_its_auditlogs( + checkListObj, isMoveToAutomation) + checkListObj.state = CheckListState.archive.name # @UndefinedVariable + checkListObj.owner = checkListObj.creator + checkListObj.update_time = timezone.now() + + checkListObj.save() + + return checklistDupObject + + +def set_state_to_automation(checkListObj=None): + if checkListObj is None: + checkListObj = retrieve_checklist_object(request_data_mgr.get_cl_uuid()) + + if checkListObj.associated_files == [] or not checkListObj.associated_files: + logger.error( + "set_state_to_automation failed: no files were found in the checkListObj.associated_file") + msg = "checklist state wasn't change, please add files to the checklist in order to start Automation state" + raise KeyError(msg) + originalState = checkListObj.state + checkListObj.state = CheckListState.automation.name # @UndefinedVariable + checkListObj.update_time = timezone.now() + + checkListObj.save() + + if originalState == CheckListState.pending.name: # @UndefinedVariable + send_cl_from_pending_to_automation_event(checkListObj) + + +def set_state_to_review(checkListObj): + checkListObj.state = CheckListState.review.name # @UndefinedVariable + checkListObj.update_time = timezone.now() + # set the owner to reviewer and update_or_insert_to_recent_engagements(...) + + checkListObj.save() + + +@auth(Permissions.el_review_checklist, is_internal=True) +def set_state_to_peer_review(): + """ + This method is called when EL approves a review and moves a CL to peer_review + """ + checkListObj = retrieve_checklist_and_its_decisions( + request_data_mgr.get_cl_uuid(), 'review_value') # @UndefinedVariable + checkListObj.state = CheckListState.peer_review.name # @UndefinedVariable + checkListObj.owner = checkListObj.engagement.peer_reviewer + + insert_to_recent_engagements( + owner=checkListObj.owner, action=RecentEngagementActionType.GOT_OWNERSHIP_OVER_ENGAGEMENT.name) # @UndefinedVariable + + checkListObj.update_time = timezone.now() + + checkListObj.save() + + +@auth(Permissions.peer_review_checklist, is_internal=True) +def set_state_to_approval(): + """ + This method is called when Peer Reviewer approves a review and moves a CL to approval state + """ + checkListObj = retrieve_checklist_and_its_decisions( + request_data_mgr.get_cl_uuid(), 'peer_review_value') # @UndefinedVariable + checkListObj.state = CheckListState.approval.name # @UndefinedVariable + admin_role = Role.objects.get(name=Roles.admin.name) # @UndefinedVariable + + admin_list = IceUserProfile.objects.all().filter( + role=admin_role) # @UndefinedVariable + if admin_list.count() < 1: + logger.error("Failed to save the new state of the Checklist to the DB") + msg = "checklist state wasn't change due to server error" + raise Exception(msg) + + rand_admin = admin_list[random.randint(0, admin_list.count() - 1)] + admin = IceUserProfile.objects.get(uuid=rand_admin.uuid) + + checkListObj.update_time = timezone.now() + checkListObj.owner = admin + insert_to_recent_engagements( + owner=checkListObj.owner, action=RecentEngagementActionType.GOT_OWNERSHIP_OVER_ENGAGEMENT.name) # @UndefinedVariable + + checkListObj.save() + + +@auth(Permissions.admin_approve_checklist) +def set_state_to_handoff(): + """ + This method is called when an admin approves a CL and moves it to a handoff state + """ + checkListObj = retrieve_checklist_and_its_decisions( + request_data_mgr.get_cl_uuid(), '') + checkListObj.state = CheckListState.handoff.name # @UndefinedVariable + checkListObj.owner = checkListObj.creator + + insert_to_recent_engagements( + owner=checkListObj.owner, action=RecentEngagementActionType.GOT_OWNERSHIP_OVER_ENGAGEMENT.name) # @UndefinedVariable + + checkListObj.update_time = timezone.now() + + checkListObj.save() + + +@auth(Permissions.handoff_checklist) +def set_state_to_closed(): + """ + This method is called when an EL approves the handoff and moves the CL to closed state + """ + checkListObj = retrieve_checklist_and_its_decisions( + request_data_mgr.get_cl_uuid(), '') + checkListObj.state = CheckListState.closed.name # @UndefinedVariable + checkListObj.owner = checkListObj.creator + checkListObj.update_time = timezone.now() + update_eng_validation_details(checkListObj) + checkListObj.save() diff --git a/django/engagementmanager/service/cms/__init__.py b/django/engagementmanager/service/cms/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/service/cms/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/service/cms/base_cms.py b/django/engagementmanager/service/cms/base_cms.py new file mode 100755 index 0000000..8625d88 --- /dev/null +++ b/django/engagementmanager/service/cms/base_cms.py @@ -0,0 +1,51 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from abc import ABCMeta +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class BaseCms(): + ''' + classdocs This is the base abstract class of all ice cms operations + ''' + __metaclass__ = ABCMeta + + logger = LoggingServiceFactory.get_logger() diff --git a/django/engagementmanager/service/cms/pages_service.py b/django/engagementmanager/service/cms/pages_service.py new file mode 100755 index 0000000..ab6fc96 --- /dev/null +++ b/django/engagementmanager/service/cms/pages_service.py @@ -0,0 +1,68 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import re + +from engagementmanager.apps import cms_client +from engagementmanager.service.cms.base_cms import BaseCms + + +class CMSPagesService(BaseCms): + + def __init__(self, params=None): + pass + + def getPages(self, title=""): + pages = cms_client.get_pages(title) + + return pages + + def getPage(self, id): + page = cms_client.get_page(id) + + # Handling static files address (like images) to get the full address of the CMS static file: + if 'content' in page and page['content']: + cmsAddress = re.sub('\/api/$', '', cms_client.api_url) + page['content'] = page['content'].replace('src="/static/media/', 'src="%s/static/media/' % cmsAddress) + + return page + + def searchPages(self, keyword): + pages = cms_client.search_pages(keyword)[:100] + + return pages diff --git a/django/engagementmanager/service/cms/posts_service.py b/django/engagementmanager/service/cms/posts_service.py new file mode 100755 index 0000000..720f766 --- /dev/null +++ b/django/engagementmanager/service/cms/posts_service.py @@ -0,0 +1,58 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from datetime import datetime, timedelta + +from engagementmanager.apps import cms_client +from engagementmanager.service.cms.base_cms import BaseCms + + +class CMSPostsService(BaseCms): + + def __init__(self, params=None): + pass + + def getPosts(self, offset, limit, fromLastDays=None, category=""): + from_last_days_param = "" + + if (fromLastDays is not None and fromLastDays != ""): + from_last_days_param = (datetime.now() - timedelta(days=int(fromLastDays))).strftime('%Y-%m-%d') + + posts = cms_client.get_posts(offset, limit, category, from_last_days_param) + + return posts diff --git a/django/engagementmanager/service/deploment_target_service.py b/django/engagementmanager/service/deploment_target_service.py new file mode 100755 index 0000000..69c5e6f --- /dev/null +++ b/django/engagementmanager/service/deploment_target_service.py @@ -0,0 +1,47 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.models import VF, DeploymentTarget + + +def update_deployment_target(engagement_uuid, dt_uuid): + + vf = VF.objects.get(engagement__uuid=engagement_uuid) + dpltarget = DeploymentTarget.objects.get(uuid=dt_uuid) + vf.deployment_target = dpltarget + vf.save() diff --git a/django/engagementmanager/service/ecomp_service.py b/django/engagementmanager/service/ecomp_service.py new file mode 100755 index 0000000..d151ac0 --- /dev/null +++ b/django/engagementmanager/service/ecomp_service.py @@ -0,0 +1,46 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.models import VF, ECOMPRelease + + +def update_ECOMP(engagement_uuid, ecomp_uuid): + vf = VF.objects.get(engagement__uuid=engagement_uuid) + ecomp = ECOMPRelease.objects.get(uuid=ecomp_uuid) + vf.ecomp_release = ecomp + vf.save() diff --git a/django/engagementmanager/service/engagement_service.py b/django/engagementmanager/service/engagement_service.py new file mode 100755 index 0000000..628bc57 --- /dev/null +++ b/django/engagementmanager/service/engagement_service.py @@ -0,0 +1,689 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from datetime import datetime, timedelta +from django.conf import settings +from django.core.exceptions import PermissionDenied +from django.db import connection +from django.db.models.aggregates import Count +from django.db.models.expressions import F +from django.db.models.query_utils import Q +from django.utils import timezone +from django.utils.datastructures import OrderedSet +from engagementmanager.bus.messages.activity_event_message import \ + ActivityEventMessage +from engagementmanager.slack_client.api import SlackClient +from engagementmanager.models import VF, Engagement, RecentEngagement, \ + EngagementStatus, VFC, IceUserProfile, Checklist +from engagementmanager.serializers import SuperThinIceUserProfileModelSerializer, \ + VFModelSerializerForSignal +from engagementmanager.utils.constants import Roles, EngagementStage, \ + ChecklistDefaultNames +from engagementmanager.utils.dates import parse_date +from engagementmanager.utils.activities_data import \ + ChangeEngagementStageActivityData +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.vm_integration import vm_client +from validationmanager.utils.clients import get_gitlab_client +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def update_engagement_status(user, description, eng_status_uuid, engagement): + try: + status = EngagementStatus.objects.get(uuid=eng_status_uuid) + status.description = description + status.update_time = timezone.now() + status.save() + msg = "Status was successfully updated with a for engagement with uuid: " + \ + engagement.uuid + logger.debug(msg) + except RecentEngagement.DoesNotExist: + EngagementStatus.objects.create( + creator=user, description=description) + msg = "Status was successfully created with a for engagement with uuid: " + \ + engagement.uuid + logger.debug(msg) + + +def insert_engagement_status(user, description, engagement): + created_eng = EngagementStatus.objects.create( + creator=user, description=description, engagement=engagement) + msg = "Status was successfully created with a for engagement with uuid: " + \ + engagement.uuid + logger.debug(msg) + return created_eng + + +def update_or_insert_to_recent_engagements(original_user_uuid, vf, action_type): + try: + user_uuid = '' + try: + user_uuid = original_user_uuid.urn[9:] + except: + user_uuid = original_user_uuid + recent_engs = RecentEngagement.objects.filter( + user_uuid=user_uuid, vf=vf.uuid).order_by('-last_update') + + if len(recent_engs) == 0: + raise RecentEngagement.DoesNotExist() + else: + recent_eng = recent_engs[0] + + if (recent_eng.action_type != action_type): + recent_eng.action_type = action_type + recent_eng.last_update = timezone.now() + msg = "Recent engagement table was successfully updated the row for a user with uuid: " + \ + user_uuid + " and vf uuid: " + vf.uuid + \ + "with a new action type: " + action_type + logger.debug(msg) + recent_eng.save() + else: + recent_eng.last_update = timezone.now() + msg = "Recent engagement table was successfully updated the last_update row for a user with uuid: " + \ + user_uuid + " and vf uuid: " + vf.uuid + logger.debug(msg) + recent_eng.save() + RecentEngagement.objects.filter( + last_update__lt=datetime.now() - timedelta(days=settings.RECENT_ENG_TTL)).delete() + except RecentEngagement.DoesNotExist: + RecentEngagement.objects.create( + user_uuid=user_uuid, vf=vf, action_type=action_type) + msg = "Recent engagement table was successfully updated with a new row for a user with uuid: " + \ + str(user_uuid) + " and vf uuid: " + str(vf.uuid) + logger.debug(msg) + + +def get_dashboard_expanded_engs(stage, keyword, offset, limit, user): + """ + Expecting: + stage: one of the choices in the defined constants. + keyword: string + offset: non-negative number to start the pull from them + 9 (Negative indexing (i.e. Entry.objects.all()[-1]) is not supported - according to Django 21.12.16). + user: user object of the requesting client. + Result: + Query-set of engs that match the parameters provided (10 objects). + """ + engStageList = [EngagementStage.Intake.name, EngagementStage.Active.name, + EngagementStage.Validated.name, EngagementStage.Completed.name] # @UndefinedVariable + + q_object = Q() + q_vfc_object = Q() + if len(keyword) >= 1: + q_object &= Q(name__icontains=keyword) | Q( + engagement__engagement_manual_id__icontains=keyword) | Q( + engagement__engagement_team__email__icontains=keyword) | Q( + engagement__engagement_team__full_name__icontains=keyword) + q_vfc_object &= Q(name__icontains=keyword) + + if stage == "All": + q_object &= Q(engagement__engagement_stage__in=engStageList) + q_vfc_object &= Q(vf__engagement__engagement_stage__in=engStageList) + else: + q_object &= Q(engagement__engagement_stage=stage) + q_vfc_object &= Q(vf__engagement__engagement_stage=stage) + + # @UndefinedVariable + if (user.role.name != Roles.admin.name and user.role.name != Roles.admin_ro.name): + q_object &= Q(engagement__engagement_team__uuid=user.uuid) + q_vfc_object &= Q(vf__engagement__engagement_team__uuid=user.uuid) + + vf_list_uuids = VF.objects.filter(q_object).values_list( + 'uuid', flat=True).order_by('engagement__target_completion_date') + vfc_vflist_uuids = VFC.objects.filter(q_vfc_object).values_list( + 'vf__uuid', flat=True).order_by('vf__engagement__target_completion_date') + + vf_list_uuids = OrderedSet(vf_list_uuids) + for current_vf in OrderedSet(vfc_vflist_uuids): + vf_list_uuids.add(current_vf) + num_of_objects = len(vf_list_uuids) + + vf_final_array = [] + vf_list = VF.objects.filter(uuid__in=vf_list_uuids)\ + .annotate(vf__name=F('name'), vendor__name=F('vendor__name'), + )\ + .values( + 'vf__name', + 'version', + 'deployment_target__version', + 'engagement__peer_reviewer__uuid', + 'ecomp_release__name', + 'engagement__engagement_stage', + 'engagement__engagement_manual_id', + 'engagement__uuid', + 'engagement__heat_validated_time', + 'engagement__image_scan_time', + 'engagement__aic_instantiation_time', + 'engagement__asdc_onboarding_time', + 'engagement__target_completion_date', + 'engagement__progress', + 'target_lab_entry_date', + 'engagement__started_state_time', + 'vendor__name', + 'engagement__validated_time', + 'engagement__completed_time', + 'uuid' + )\ + .annotate(vf_uuid_count=Count('uuid', distinct=True))\ + .order_by('engagement__target_completion_date')[int(offset):int(offset) + limit] + for current_vf in vf_list: + eng = Engagement.objects.get(uuid=current_vf['engagement__uuid']) + starred_users = eng.starred_engagement.all() + current_vf['starred_users'] = list() + if starred_users: + for current_starred in starred_users: + current_vf['starred_users'].append(current_starred.uuid) + vf_final_array.append(current_vf) + data = {'array': vf_final_array, 'num_of_objects': num_of_objects} + return data + +# Extension method for get_dashboard_expanded_engs which adds additional +# data required by export process. + + +def get_expanded_engs_for_export(stage, keyword, user): + # TODO replace this 1000000 with No limit value + data = get_dashboard_expanded_engs( + stage, keyword, 0, 10000000, user) + + vf_list = data["array"] + + for vf in vf_list: + eng = Engagement.objects.get(uuid=vf['engagement__uuid']) + latest_status = EngagementStatus.objects.filter( + engagement=eng).distinct().order_by('-update_time')[:1] + peer_reviewer = eng.peer_reviewer + reviewer = eng.reviewer + vf['vf_engagement__peer_reviewer'] = peer_reviewer + vf['vf_engagement__reviewer'] = reviewer + if latest_status.count() > 0: + vf['engagement__latest_status'] = latest_status[0].description + else: + vf['engagement__latest_status'] = "--" + + vf['vfcs'] = "--" + vf['vfcs__number'] = "0" + vfObject = VF.objects.get(uuid=vf['uuid']) + if vfObject is not None: + vfcs = vfObject.vfc_set.values_list('name', flat=True) + if vfcs.count() > 0: + vf['vfcs'] = ', '.join(vfcs) + vf['vfcs__number'] = vfcs.count() + + # Overview statistics: + cursor = connection.cursor() + cursor.callproc("generate_excel_overview_sheet", (stage, keyword,)) + deployment_targets = cursor.fetchall() + cursor.execute("COMMIT") + + return vf_list, deployment_targets + + +def is_eng_stage_eql_to_requested_one(engagement, requested_stage): + if engagement.engagement_stage == requested_stage: + msg = "An attempt to change the Engagement's stage (uuid: " + engagement.uuid + \ + ") to the same stage it is current in(" + \ + engagement.engagement_stage + ") was made." + logger.debug(msg) + return True + return False + + +def set_engagement_stage(eng_uuid, stage): + engagement = Engagement.objects.get(uuid=eng_uuid) + vfObj = engagement.vf + if is_eng_stage_eql_to_requested_one(engagement, stage): + msg = "Action denied." + raise ValueError(msg) + else: + engagement.engagement_stage = stage + engagement.intake_time = timezone.now() + engagement.save() + vm_client.fire_event_in_bg('send_provision_new_vf_event', vfObj) + msg = send_notifications_and_create_activity_after_eng_stage_update( + engagement) + return msg + + +def send_notifications_and_create_activity_after_eng_stage_update(engagement): + # send notifications + res = get_engagement_manual_id_and_vf_name(engagement) + slack_client = SlackClient() + slack_client.update_for_change_of_the_engagement_stage( + res['engagement_manual_id'], res['vf_name'], engagement.engagement_stage) + + activity_data = ChangeEngagementStageActivityData(VF.objects.get(engagement=engagement), engagement.engagement_stage, + engagement) + from engagementmanager.apps import bus_service + bus_service.send_message(ActivityEventMessage(activity_data)) + + logger.debug("Engagement's stage (eng_uuid: " + engagement.uuid + ") was successfully changed to: " + + engagement.engagement_stage) + return "OK" + + +def set_progress_for_engagement(progress=None): + prog = int(progress) + if prog < 0 or prog > 100: + msg = 'set_progress_for_engagement failed: Progress value is invalid (out of bounds). Should be 0-100' + logger.debug(msg) + raise ValueError(msg) + else: + eng = Engagement.objects.get(uuid=request_data_mgr.get_eng_uuid()) + eng.progress = progress + eng.save() + + +def vf_retreiver(user, star=False, recent=False, eng_uuid=""): + engStageList = [EngagementStage.Intake.name, EngagementStage.Active.name, + EngagementStage.Validated.name, EngagementStage.Completed.name] # @UndefinedVariable + # @UndefinedVariable + if (user.role.name == Roles.admin.name or user.role.name == Roles.admin_ro.name): + if star: + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList)\ + .filter(engagement__starred_engagement__uuid=user.uuid).distinct().order_by('engagement__engagement_manual_id')\ + .values( + 'uuid', + 'name', + 'is_service_provider_internal', + 'engagement__creator__uuid', + 'engagement__engagement_manual_id', + 'engagement__peer_reviewer__uuid', + 'engagement__peer_reviewer__email', + 'engagement__reviewer__uuid', + 'engagement__reviewer__email', + 'engagement__uuid' + ) + + for vf in vf_list: + red_dot_activity = RecentEngagement.objects.filter( + vf=vf['uuid']).values('action_type').order_by('-last_update')[:1] + if (red_dot_activity.count() > 0): + vf['action_type'] = red_dot_activity[0]['action_type'] + else: + vf['action_type'] = '' + + return vf_list + + elif recent: + recent = RecentEngagement.objects.filter(vf__engagement__engagement_stage__in=engStageList)\ + .filter(user_uuid=user.uuid).distinct().order_by('-last_update')\ + .values( + 'vf__uuid', + 'vf__name', + 'vf__is_service_provider_internal', + 'vf__engagement__creator__uuid', + 'vf__engagement__engagement_manual_id', + 'vf__engagement__peer_reviewer__uuid', + 'vf__engagement__peer_reviewer__email', + 'vf__engagement__reviewer__uuid', + 'vf__engagement__reviewer__email', + 'vf__engagement__uuid', + 'action_type', + 'last_update' + )[:20] + return recent + + else: + if eng_uuid != "": + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList)\ + .filter(engagement__uuid=eng_uuid).distinct().order_by('engagement__engagement_manual_id')\ + .values( + 'uuid', + 'name', + 'is_service_provider_internal', + 'engagement__creator__uuid', + 'engagement__engagement_manual_id', + 'engagement__peer_reviewer__uuid', + 'engagement__peer_reviewer__email', + 'engagement__reviewer__uuid', + 'engagement__reviewer__email', + 'engagement__uuid' + ) + else: + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList)\ + .filter().distinct().order_by('engagement__engagement_manual_id')\ + .values( + 'uuid', + 'name', + 'is_service_provider_internal', + 'engagement__creator__uuid', + 'engagement__engagement_manual_id', + 'engagement__peer_reviewer__uuid', + 'engagement__peer_reviewer__email', + 'engagement__reviewer__uuid', + 'engagement__reviewer__email', + 'engagement__uuid' + ) + + return vf_list + else: + if star: + if eng_uuid != "": + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList)\ + .filter(Q(engagement__uuid=eng_uuid, engagement__engagement_team__uuid=user.uuid, engagement__starred_engagement__uuid=user.uuid) | Q(engagement__uuid=eng_uuid, engagement__peer_reviewer=user, engagement__starred_engagement__uuid=user.uuid))\ + .values( + 'uuid', + 'name', + 'is_service_provider_internal', + 'engagement__creator__uuid', + 'engagement__engagement_manual_id', + 'engagement__peer_reviewer__uuid', + 'engagement__peer_reviewer__email', + 'engagement__reviewer__uuid', + 'engagement__reviewer__email', + 'engagement__uuid' + ) + else: + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList)\ + .filter(Q(engagement__engagement_team__uuid=user.uuid, engagement__starred_engagement__uuid=user.uuid) | Q(engagement__peer_reviewer=user, engagement__starred_engagement__uuid=user.uuid)).distinct().order_by('engagement__engagement_manual_id')\ + .values( + 'uuid', + 'name', + 'is_service_provider_internal', + 'engagement__creator__uuid', + 'engagement__engagement_manual_id', + 'engagement__peer_reviewer__uuid', + 'engagement__peer_reviewer__email', + 'engagement__reviewer__uuid', + 'engagement__reviewer__email', + 'engagement__uuid' + ) + for vf in vf_list: + red_dot_activity = RecentEngagement.objects.filter( + vf=vf['uuid']).values('action_type').order_by('-last_update')[:1] + if (red_dot_activity.count() > 0): + vf['action_type'] = red_dot_activity[0]['action_type'] + else: + vf['action_type'] = '' + + return vf_list + + elif recent: + recent = RecentEngagement.objects.filter(vf__engagement__engagement_stage__in=engStageList)\ + .filter(Q(user_uuid=user.uuid, vf__engagement__engagement_team__uuid=user.uuid) | Q(user_uuid=user.uuid, vf__engagement__peer_reviewer=user)).distinct().order_by('-last_update')\ + .values( + 'vf__uuid', + 'vf__name', + 'vf__is_service_provider_internal', + 'vf__engagement__creator__uuid', + 'vf__engagement__engagement_manual_id', + 'vf__engagement__peer_reviewer__uuid', + 'vf__engagement__peer_reviewer__email', + 'vf__engagement__reviewer__uuid', + 'vf__engagement__reviewer__email', + 'vf__engagement__uuid', + 'action_type', + 'last_update' + )[:20] + return recent + else: + if eng_uuid != "": + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList)\ + .filter(Q(engagement__uuid=eng_uuid, engagement__engagement_team__uuid=user.uuid) | Q(engagement__uuid=eng_uuid, engagement__peer_reviewer=user)).distinct().order_by('engagement__engagement_manual_id')\ + .values( + 'uuid', + 'name', + 'is_service_provider_internal', + 'engagement__creator__uuid', + 'engagement__engagement_manual_id', + 'engagement__peer_reviewer__uuid', + 'engagement__peer_reviewer__email', + 'engagement__reviewer__uuid', + 'engagement__reviewer__email', + 'engagement__uuid' + ) + else: + vf_list = VF.objects.filter(engagement__engagement_stage__in=engStageList)\ + .filter(Q(engagement__engagement_team__uuid=user.uuid) | Q(engagement__peer_reviewer=user)).distinct().order_by('engagement__engagement_manual_id')\ + .values( + 'uuid', + 'name', + 'is_service_provider_internal', + 'engagement__creator__uuid', + 'engagement__engagement_manual_id', + 'engagement__peer_reviewer__uuid', + 'engagement__peer_reviewer__email', + 'engagement__reviewer__uuid', + 'engagement__reviewer__email', + 'engagement__uuid' + ) + return vf_list + + +def star_an_engagement(user, eng_uuid): + msg = "Engagement was successfully starred." + engObj = None + try: + engObj = Engagement.objects.get( + uuid=eng_uuid, starred_engagement__uuid=user.uuid) + engObj.starred_engagement.remove(user) + msg = "Engagement was successfully un-starred." + except Engagement.DoesNotExist: + engObj = Engagement.objects.get(uuid=eng_uuid) + engObj.starred_engagement.add(user) + engObj.save() + + return msg + + +def archive_engagement(eng_uuid, reason): + msg = "Engagement was successfully archived." + engagement = Engagement.objects.get(uuid=eng_uuid) + # get the vf + vf = VF.objects.get(engagement__uuid=engagement.uuid) + gitlab = get_gitlab_client() + project_id = "%s/%s" % (vf.engagement.engagement_manual_id, + vf.name.replace(' ', '_')) + formated_vf = VFModelSerializerForSignal(vf).data + + # @UndefinedVariable + engagement.engagement_stage = EngagementStage.Archived.name + engagement.archive_reason = reason + engagement.archived_time = timezone.now() + engagement.save() + vm_client.send_remove_all_standard_users_from_project_event( + gitlab, project_id, formated_vf) + # send notifications + res = get_engagement_manual_id_and_vf_name(engagement) + slack_client = SlackClient() + slack_client.update_for_archived_engagement( + res['engagement_manual_id'], res['vf_name'], reason) + return msg + + +def set_engagement_reviewer(eng_uuid, reviewer_uuid): + result = None + engagement = Engagement.objects.get(uuid=eng_uuid) + + reviewer = IceUserProfile.objects.get(uuid=reviewer_uuid) + if engagement.peer_reviewer != reviewer: + old_reviewer = engagement.reviewer + engagement.engagement_team.remove(old_reviewer) + engagement.engagement_team.add(reviewer) + + checklist_lists_creator = Checklist.objects.filter( + engagement__uuid=eng_uuid, creator=old_reviewer) + for checklist in checklist_lists_creator: + checklist.creator = reviewer + checklist.save() + + checklist_lists_owner = Checklist.objects.filter( + engagement__uuid=eng_uuid, owner=old_reviewer) + for checklist in checklist_lists_owner: + checklist.owner = reviewer + checklist.save() + + engagement.reviewer = reviewer + engagement.save() + + # send notifications + res = get_engagement_manual_id_and_vf_name(engagement) + slack_client = SlackClient() + slack_client.update_reviewer_or_peer_reviewer( + res['engagement_manual_id'], res['vf_name'], reviewer, old_reviewer, 'reviewer') + + result = reviewer + else: + return result + + return SuperThinIceUserProfileModelSerializer(result).data + + +def set_engagement_peer_reviewer(eng_uuid, peer_reviewer_uuid): + result = None + engagement = Engagement.objects.get(uuid=eng_uuid) + peer_reviewer = IceUserProfile.objects.get(uuid=peer_reviewer_uuid) + if engagement.reviewer != peer_reviewer: + old_peer_reviewer = engagement.peer_reviewer + engagement.engagement_team.remove(old_peer_reviewer) + engagement.engagement_team.add(peer_reviewer) + + checklist_lists_owner = Checklist.objects.filter( + engagement__uuid=eng_uuid, owner=old_peer_reviewer) + for checklist in checklist_lists_owner: + checklist.owner = peer_reviewer + checklist.save() + + engagement.peer_reviewer = peer_reviewer + engagement.save() + + # send notifications + res = get_engagement_manual_id_and_vf_name(engagement) + slack_client = SlackClient() + slack_client.update_reviewer_or_peer_reviewer( + res['engagement_manual_id'], res['vf_name'], peer_reviewer, old_peer_reviewer, 'peer reviewer') + + result = peer_reviewer + else: + return result + + return SuperThinIceUserProfileModelSerializer(result).data + + +def switch_engagement_reviewers(eng_uuid, reviewer_uuid, peer_reviewer_uuid): + engagement = Engagement.objects.get(uuid=eng_uuid) + peer_reviewer = IceUserProfile.objects.get(uuid=peer_reviewer_uuid) + old_peer_reviewer = engagement.peer_reviewer + reviewer = IceUserProfile.objects.get(uuid=reviewer_uuid) + old_reviewer = engagement.reviewer + + checklist_owners = Checklist.objects.filter( + Q(engagement__uuid=eng_uuid) & (Q(owner=old_reviewer) | Q(owner=old_peer_reviewer))) + + for checklist in checklist_owners: + if checklist.owner == reviewer: + checklist.owner = peer_reviewer + if checklist.owner == peer_reviewer: + checklist.owner = reviewer + checklist.save() + + engagement.peer_reviewer = peer_reviewer + engagement.reviewer = reviewer + engagement.save() + + # send notifications + res = get_engagement_manual_id_and_vf_name(engagement) + slack_client = SlackClient() + slack_client.update_reviewer_or_peer_reviewer( + res['engagement_manual_id'], res['vf_name'], reviewer, old_reviewer, 'reviewer') + slack_client.update_reviewer_or_peer_reviewer( + res['engagement_manual_id'], res['vf_name'], peer_reviewer, old_peer_reviewer, 'peer reviewer') + + return {"reviewer": reviewer_uuid, "peerreviewer": peer_reviewer_uuid} + + +def get_engagement_manual_id_and_vf_name(engagement): + # get the engagement + engagement_manual_id = engagement.engagement_manual_id + + # get the vf + vf = VF.objects.get(engagement__uuid=engagement.uuid) + vf_name = "" + if vf is not None: + vf_name = vf.name + + return {'engagement_manual_id': engagement_manual_id, 'vf_name': vf_name} + + +def update_engagement(engagement_dict): + engagement = Engagement.objects.get(uuid=engagement_dict['uuid']) + + engagement.target_completion_date = parse_date( + engagement_dict['target_completion_date']) + engagement.heat_validated_time = parse_date( + engagement_dict['heat_validated_time']) + engagement.image_scan_time = parse_date(engagement_dict['image_scan_time']) + engagement.aic_instantiation_time = parse_date( + engagement_dict['aic_instantiation_time']) + engagement.asdc_onboarding_time = parse_date( + engagement_dict['asdc_onboarding_time']) + if 0 <= engagement_dict['progress'] <= 100: + engagement.progress = engagement_dict['progress'] + else: + return None + + engagement.save() + return engagement + + +def remove_user_from_engagement_team(eng_uuid, user, removed_user_uuid): + msg = "User was successfully removed from the engagement team" + # @UndefinedVariable + if ((removed_user_uuid == user.uuid) or (removed_user_uuid != user.uuid and (user.role.name == Roles.admin.name or user.role.name == Roles.el.name))): + engagement = Engagement.objects.get(uuid=eng_uuid) + requested_user = IceUserProfile.objects.get(uuid=removed_user_uuid) + if (engagement.peer_reviewer == requested_user or engagement.reviewer == requested_user + or engagement.creator == requested_user or engagement.contact_user == requested_user): + msg = "Reviewer/Peer Reviewer/Creator/Contact user cannot be removed from engagement team." + logger.error(msg) + raise PermissionDenied + engagement.engagement_team.remove(requested_user) + engagement.save() + logger.debug(msg) + else: + msg = "removed user is not equal to conducting user or user is not an admin." + logger.error(msg) + raise PermissionDenied + + +def update_eng_validation_details(cl): + setattr(cl.engagement, + ChecklistDefaultNames.VALIDATION_DATE_ARRAY[cl.name], timezone.now()) + cl.engagement.save() diff --git a/django/engagementmanager/service/invite_service.py b/django/engagementmanager/service/invite_service.py new file mode 100755 index 0000000..c4780fd --- /dev/null +++ b/django/engagementmanager/service/invite_service.py @@ -0,0 +1,179 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from datetime import datetime, timedelta +from uuid import uuid4 +import bleach +from django.conf import settings +from django.template.loader import get_template +from engagementmanager import mail +from engagementmanager.models import Invitation, IceUserProfile, Engagement +from engagementmanager.utils.constants import Roles, Constants +from engagementmanager.utils.vvp_exceptions import VvpBadRequest +from engagementmanager.utils.validator import Validator, logEncoding +from engagementmanager.views_helper import getVfByEngUuid +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def enforce_invitation_throttling(eng_uuid, invited_email, inviterUser, invitedUser): + assert eng_uuid is not None + assert invited_email is not None + + invitation = Invitation.objects.filter(engagement_uuid=eng_uuid, email=invited_email) + if len(invitation) > 0: + logger.warn("Oops, looks like an invitation with following details already exists: " + str(invitation)) + return False + + if ((invitedUser != None and invitedUser.role.name != Roles.admin.name and + invitedUser.role.name != Roles.el.name) or invitedUser == None): + numOfInvitationinLast24H = Invitation.objects.filter(email=invited_email, + create_time__gte=datetime.now() - timedelta( + hours=24)).count() + if numOfInvitationinLast24H >= 5: + logger.warn( + "Oops, looks like invited email (" + invited_email + ") which isn't EL nor admin has reached its " + "max invitations (5) in the last 24 hours") + return False + + if ((invitedUser != None and invitedUser.role.name == Roles.standard_user.name) or + (invitedUser != None and invitedUser.role.name == Roles.admin_ro.name) or + invitedUser == None): + numOfInvitationinLast24H = Invitation.objects.filter(invited_by_user_uuid=inviterUser.uuid, + create_time__gte=datetime.now() - timedelta( + hours=24)).count() + if numOfInvitationinLast24H >= 25: + logger.warn( + "Oops, looks like a standard-user/admin-readonly inviter " + "(" + inviterUser.email + ") has reached its max invitations (25) in the last 24 hours") + return False + return True + + +def generateInviteMail(data, inviterUser, invitedUser, is_contact_user): + vf = getVfByEngUuid(data['eng_uuid']) + if vf is not None: + data['vf_name'] = vf.name + else: + data['vf_name'] = "-" + logger.error("Couldn't fetch VF by engagement uuid=" + logEncoding(data['eng_uuid'])) + + body = get_template("{invite_template_dir}invite_mail_body.html".format( + invite_template_dir=Constants.invite_template_dir)) + subject = get_template("{invite_template_dir}invite_mail_subject.html".format( + invite_template_dir=Constants.invite_template_dir)) + + data['dashboard_link'] = str(settings.DOMAIN) + "/#/dashboard/" + invitation = Invitation.objects.create(engagement_uuid=data['eng_uuid'], + invited_by_user_uuid=inviterUser.uuid, email=data['email'], + invitation_token=uuid4()) + + if invitedUser is not None: + data['invite_link'] = str(settings.DOMAIN) + "/#/login?invitation=" + str(invitation.invitation_token) + data['instruction'] = "To accept this invitation, please click this link:" + logger.debug("Invited Contact with email " + data['email'] + "already exist in the DB. Sending them an email " + "with link to login page. link=" + data[ + 'invite_link']) + if is_contact_user: + logger.debug("Updating the Engagement with uuid=" + data[ + 'eng_uuid'] + " to have this contact user: " + invitedUser.full_name) + engObj = Engagement.objects.get(uuid=data['eng_uuid']) + engObj.contact_user = invitedUser + engObj.save() + + else: + prefix = str(settings.DOMAIN) + "/#/signUp?invitation=" + \ + str(invitation.invitation_token) + "&email=" + data['email'] + suffix = "" + if 'full_name' in data and data['full_name'] and 'phone_number' in data and data['phone_number']: + suffix += "&full_name=" + data['full_name'] + "&phone_number=" + data['phone_number'] + if data.get('company'): + suffix += "&company=" + data['company'] + + data['invite_link'] = prefix + suffix + data['instruction'] = "To create an account and accept this invitation, please click this link:" + + if is_contact_user: + data['invite_link'] += "&is_contact_user=true" + logger.debug("The invite mail is sent to a contact person (VF Contact or " + + Constants.service_provider_company_name + " Sponsor)") + + logger.debug( + "Invited Person doesn't exists, sending them an email with link to signup. link=" + data['invite_link']) + + return body, subject, invitation + + +def inviteUserToSignUpOrLogin(inviterUser, data, is_contact_user): + invitedUser = None + + Validator.validateEmail(data['email']) + + data['email'] = bleach.clean(data['email'], tags=['a', 'b']) + rs = IceUserProfile.objects.filter(email=data['email']) + + if len(rs) > 0: + invitedUser = IceUserProfile.objects.get(email=data['email']) + + is_invite_ok = enforce_invitation_throttling(data['eng_uuid'], data['email'], inviterUser, invitedUser) + + if is_invite_ok == False: + msg = "Invite couldn't be created" + logger.error(msg) + raise VvpBadRequest(msg) + + body, subject, invitation = generateInviteMail(data, inviterUser, invitedUser, is_contact_user) + + try: + mail.sendMail(data['email'], data, body, subject) + except Exception as e: + logger.error(e) + msg = "Something went wrong while trying to send mail to " + data['email'] + " from " + inviterUser.email + logger.error(msg) + if invitation: + logger.error("Rolling back the invitation (" + invitation + ") due to problems in sending its mail") + invitation.delete() + raise Exception(msg) + + +def markInvitationAsAccepted(invitation_token): + invitation = Invitation.objects.get(invitation_token=invitation_token) + invitation.accepted = True + invitation.save() + logger.debug("Marking Invitation [" + str(invitation) + "] as accepted") diff --git a/django/engagementmanager/service/logging_service.py b/django/engagementmanager/service/logging_service.py new file mode 100755 index 0000000..b90bdbf --- /dev/null +++ b/django/engagementmanager/service/logging_service.py @@ -0,0 +1,58 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import logging + + +class LoggingServiceFactory(object): + __logger = None + + def __init__(self): + if self.__logger is None: + self.__set_logger() + + @classmethod + def __set_logger(cls): + if cls.__logger is None: + cls.__logger = logging.getLogger('vvp.logger') + + @classmethod + def get_logger(cls): + if cls.__logger is None: + cls.__set_logger() + return cls.__logger diff --git a/django/engagementmanager/service/login_service.py b/django/engagementmanager/service/login_service.py new file mode 100755 index 0000000..7216b56 --- /dev/null +++ b/django/engagementmanager/service/login_service.py @@ -0,0 +1,136 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import bleach +from django.contrib.auth import authenticate +from django.contrib.auth import get_user_model +from django.contrib.auth.hashers import check_password +from django.core.exceptions import PermissionDenied +from django.utils import timezone +from rest_framework.exceptions import NotAcceptable + +from engagementmanager.models import Invitation, VF +from engagementmanager.serializers import ThinIceUserProfileModelSerializer +from engagementmanager.service.base_service import BaseSvc +from engagementmanager.service.invite_service import markInvitationAsAccepted +from engagementmanager.utils.vvp_exceptions import VvpConflict +from engagementmanager.utils.validator import logEncoding +from engagementmanager.views_helper import addUsersToEngTeam +from engagementmanager.vm_integration import vm_client + + +class LoginSvc(BaseSvc): + + def get_user_by_email(self, email): + user_model = get_user_model() + user = user_model._default_manager.get(email=email) + return user + + def update_last_login(self, user_profile): + user_profile.user.last_login = timezone.now() + user_profile.user.save() + user_profile.save() + + def authenticate_user(self, i_email, i_password, msg): + user = authenticate(username=i_email, password=i_password) + if not user: + msg = "User or Password does not match" + self.logger.error(msg) + raise PermissionDenied(msg) + return user + + def reset_password(self, reset_password_email, i_password, msg, user_profile): + token_user = self.get_user_by_email(reset_password_email) + if user_profile.user.id != token_user.id: + msg = self.render_user_conflict_message(user_profile.user, token_user) + temp_encrypted_password = user_profile.user.temp_password + is_temp_password_ok = check_password(i_password, temp_encrypted_password) + if is_temp_password_ok: + self.logger.debug("Temporary Passwords match... Checking temporary password expiration") + else: + msg = "User or Password does not match" + self.logger.error(msg + " in Reset Password flow") + raise PermissionDenied(msg) + return msg + + def render_user_conflict_message(self, user, user_from_token): + msg = "User Conflict" + self.logger.error(msg + ". user uuid =" + user.id + ", user from token uuid=" + user_from_token.id) + raise VvpConflict + + def render_user_not_active_message(self, i_email): + msg = "User " + i_email + " is not active hence cannot perform login" + self.logger.error(msg) + msg = bleach.clean(msg, tags=['a', 'b']) + raise NotAcceptable(msg) + + def identify_reset_password(self, jwt_obj, reset_password_param): + email = None + is_reset_pwd_flow = False + + if reset_password_param is not None: + is_reset_pwd_flow = True + self.logger.debug( + "Reset Password flow is identified. Checking temporary password expiration. t=" + reset_password_param) + token_arr = reset_password_param.split("token") + if len(token_arr) > 0: + email = jwt_obj.decode_reset_password_token(str(token_arr[1])) + else: + self.logger.error("token doesn't include token prefix: " + logEncoding(reset_password_param)) + is_reset_pwd_flow = False + return email, is_reset_pwd_flow + + def handle_invite_token(self, data, user_data, user_profile): + data['invitation'] = data['invitation'].strip() + invitation = Invitation.objects.get(invitation_token=data['invitation']) + addUsersToEngTeam(invitation.engagement_uuid, [user_profile]) + vf_obj = VF.objects.get(engagement__uuid=invitation.engagement_uuid) + vm_client.fire_event_in_bg('send_provision_new_vf_event', vf_obj) + user_data['eng_uuid'] = invitation.engagement_uuid + markInvitationAsAccepted(data['invitation']) + + def get_serialized_user_data(self, is_reset_pwd_flow, user_profile, jwt_obj, user): + user_data = ThinIceUserProfileModelSerializer(user_profile).data + user_data['isResetPwdFlow'] = is_reset_pwd_flow + user_data['token'] = jwt_obj.create_token(user) + if user_profile.ssh_public_key: + user_data['ssh_public_key'] = "exists" + else: + user_data['ssh_public_key'] = "" + + return user_data diff --git a/django/engagementmanager/service/nextstep_service.py b/django/engagementmanager/service/nextstep_service.py new file mode 100755 index 0000000..9fa8672 --- /dev/null +++ b/django/engagementmanager/service/nextstep_service.py @@ -0,0 +1,280 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from django.db.models.query_utils import Q +from django.utils import timezone +from django.utils.timezone import timedelta +from engagementmanager.bus.messages.activity_event_message import ActivityEventMessage +from engagementmanager.models import Engagement, IceUserProfile, NextStep, VF +from engagementmanager.serializers import ThinNextStepModelSerializer, UserNextStepModelSerializer +from engagementmanager.utils.activities_data import UpdateNextStepsActivityData, AddNextStepsActivityData +from engagementmanager.service.engagement_service import update_or_insert_to_recent_engagements +from engagementmanager.service.base_service import BaseSvc +from engagementmanager.utils.constants import Constants, NextStepType, NextStepState, RecentEngagementActionType +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.apps import bus_service +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class NextStepSvc(BaseSvc): + default_next_steps = [ + { + 'position': 2, + 'stage': 'Intake', + 'text': 'Please work with your Engagement Lead (EL) to complete the necessary trial agreements.', + 'condition': lambda x, y: True, + 'type': NextStepType.trial_agreements.name # @UndefinedVariable + }, + { + 'position': 3, + 'stage': 'Intake', + 'text': 'Please add your ' + Constants.service_provider_company_name + ' sponsor or vendor contact information.', + 'condition': lambda user, eng: False if (eng.contact_user) else True, + 'type': NextStepType.add_contact_person.name # @UndefinedVariable + }, + { + 'position': 1, + 'stage': 'Active', + 'text': 'Please submit the first version of the VF package. If you have any problems or questions, please contact your Engagement Lead (EL)', + 'condition': lambda x, y: True, + 'type': NextStepType.submit_vf_package.name # @UndefinedVariable + }, + { + 'position': 1, + 'stage': 'Validated', + 'text': 'Please schedule a time with your Engagement Lead (EL) to complete the handoff.', + 'condition': lambda x, y: True, + 'type': NextStepType.el_handoff.name # @UndefinedVariable + } + ] + + def get_user_next_steps(self, limit, state): + user = request_data_mgr.get_user() + + nextSteps = NextStep.objects.filter(Q(assignees=user) & Q(state=state)).order_by('due_date').distinct() + count = nextSteps.count() + serializer = UserNextStepModelSerializer(nextSteps[:limit], many=True) + return serializer, count + + def get_next_steps(self, eng_stage=None): + user = request_data_mgr.get_user() + eng_uuid = request_data_mgr.get_eng_uuid() + + ers = NextStep.objects.filter(Q(engagement__uuid=eng_uuid, owner=None, engagement_stage=eng_stage) | Q( + owner=user, engagement_stage=eng_stage)).order_by('position') + + serializer = ThinNextStepModelSerializer(ers, many=True) + for next_step in serializer.data: + if next_step['files'] is not None: + next_step['files'] = json.loads(next_step['files']) + if 'engagement' in next_step and next_step['engagement'] is not None and 'engagement_team' in next_step['engagement'] and next_step['engagement']['engagement_team'] is not None: + for user in next_step['engagement']['engagement_team']: + if (user['ssh_public_key'] != None): + del user['ssh_public_key'] + return serializer + + def addNextStep(self, dataList, desc=""): + user = request_data_mgr.get_user() + checklist_uuid = request_data_mgr.get_cl_uuid() + eng_uuid = request_data_mgr.get_eng_uuid() + + nextStepObj = None + + engObj = Engagement.objects.get(uuid=eng_uuid) + vfObj = VF.objects.get(engagement=engObj) + + nextStepData = [] + due_date = None + + for data in dataList: + try: + associated_files = json.dumps(data['files'], ensure_ascii=False) + except: + associated_files = "[]" + + try: + due_date = data['duedate'] + except: + due_date = None + + nextStepObj = NextStep.objects.create(creator=user, last_updater=user, engagement=engObj, position=NextStep.objects.count() + 1, + # @UndefinedVariable + description=data[ + 'description'], state=NextStepState.Incomplete.name, engagement_stage=engObj.engagement_stage, + files=associated_files, due_date=due_date) # @UndefinedVariable + + try: + data['assigneesUuids'] + except: + data['assigneesUuids'] = [] + + for assigneesUuid in data['assigneesUuids']: + assignee_user = None + assignee_user = IceUserProfile.objects.get(uuid=assigneesUuid) + nextStepObj.assignees.add(assignee_user) + nextStepObj.save() + update_or_insert_to_recent_engagements( + assignee_user.uuid, vfObj, RecentEngagementActionType.NEXT_STEP_ASSIGNED.name) # @UndefinedVariable + + nextStepData.append(ThinNextStepModelSerializer(nextStepObj).data) + + activity_data = AddNextStepsActivityData(VF.objects.get(engagement=engObj), user, engObj) + bus_service.send_message(ActivityEventMessage(activity_data)) + + if checklist_uuid != None: + from engagementmanager.service.checklist_state_service import set_state + set_state(True, checklist_uuid, isMoveToAutomation=True, description=desc) + logger.debug("Successfully added a Next Step to engagement_uuid=" + + eng_uuid + " for checklist=" + checklist_uuid) + + return nextStepData + + ''' + This function shall return the update type in the next step (can be Completed or Denied) + ''' + + def validate_state_transition(self, user, current_state, next_state): + update_type = next_state.name + logger.debug('validating step transition by %s from %s to %s', user.role.name, current_state, next_state) + + if (current_state == NextStepState.Completed and next_state == NextStepState.Incomplete): + if (user.role.name == 'el'): + update_type = 'Denied' + else: + update_type = 'Reset' + + return update_type + + def create_default_next_steps_for_user(self, user, el_user): + def cond(user): return False if (user.ssh_public_key and user.ssh_public_key != '') else True + if cond(user): + desc = "Please add your SSH key to be able to contribute." + + nextstep = NextStep.objects.create( + creator=el_user, + last_updater=el_user, + position=1, + description=desc, + last_update_type='Added', + state='Incomplete', + engagement_stage='Intake', + engagement=None, + owner=user, + next_step_type=NextStepType.set_ssh.name, # @UndefinedVariable + due_date=timezone.now() + timedelta(days=1)) + nextstep.save() + + ''' + This method is for non-personal default next step only since it doesn't have an owner + ''' + + def create_default_next_steps(self, user, engagement, el_user): + for step in self.default_next_steps: + cond = step['condition'] + desc = step['text'] + ns_type = step['type'] + if cond(user, engagement): + if (user.company == Constants.service_provider_company): + desc = desc.replace('$Contact', 'Vendor Contact') + else: + desc = desc.replace('$Contact', Constants.service_provider_company_name + ' Sponsor Contact') + logger.debug('Creating default next step : ' + desc) + + nextstep = NextStep.objects.create(creator=el_user, last_updater=el_user, position=step['position'], description=desc, state='Incomplete', engagement_stage=step[ + 'stage'], engagement=engagement, next_step_type=ns_type, due_date=timezone.now() + timedelta(days=1)) + nextstep.assignees.add(el_user) + nextstep.save() + + else: + logger.debug('Skipping creation of default next step : ' + desc) + + def update_next_steps_order(self, nextsteps): + counter = 0 + for nextstep in nextsteps: + step = NextStep.objects.get(uuid=nextstep['uuid']) + step.position = counter + step.save() + counter += 1 + + def update_next_step(self, data): + step = NextStep.objects.get(uuid=request_data_mgr.get_ns_uuid()) + + if step.files != data['files']: + step.files = json.dumps(data['files'], ensure_ascii=False) + if data['duedate'] and data['duedate'] != step.due_date: + step.due_date = data['duedate'] + if data['description'] and step.description != data['description']: + step.description = data['description'] + if data['assigneesUuids'] != '': + for user in step.assignees.all(): + step.assignees.remove(user) + for assigneesUuid in data['assigneesUuids']: + assigned_user = IceUserProfile.objects.get(uuid=assigneesUuid) + eng_team = Engagement.objects.get(uuid=request_data_mgr.get_eng_uuid()).engagement_team.all() + if (assigned_user in eng_team): + step.assignees.add(assigned_user) + step.save() + else: + logger.error( + "An attempt to edit a NS and assign a user who is not in the engagement team was conducted, user wasn't assigned!") + continue + + step.last_updater = request_data_mgr.get_user() + step.last_update_time = timezone.now() + step.last_update_type = 'Edited' + step.save() + + def set_next_step_status(self, attr=None, state=None): + + step = NextStep.objects.get(uuid=request_data_mgr.get_ns_uuid()) + + if attr == 'state': + update_type = self.validate_state_transition( + request_data_mgr.get_user(), NextStepState[step.state], NextStepState[state]) + step.state = state + step.last_updater = request_data_mgr.get_user() + step.last_update_time = timezone.now() + step.last_update_type = update_type + step.save() + if step.engagement: + activity_data = UpdateNextStepsActivityData( + step.last_update_type, request_data_mgr.get_user(), step.engagement) + bus_service.send_message(ActivityEventMessage(activity_data)) diff --git a/django/engagementmanager/service/user_service.py b/django/engagementmanager/service/user_service.py new file mode 100755 index 0000000..8d6317e --- /dev/null +++ b/django/engagementmanager/service/user_service.py @@ -0,0 +1,121 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.contrib.auth import get_user_model +from sshpubkeys import SSHKey + +from engagementmanager.apps import bus_service +from engagementmanager.bus.messages.activity_event_message import ActivityEventMessage +from engagementmanager.models import IceUserProfile, Role, VF +from engagementmanager.serializers import SuperThinIceUserProfileModelSerializerForSignals +from engagementmanager.service.base_service import BaseSvc +from engagementmanager.utils.cryptography import CryptographyText +from engagementmanager.utils.activities_data import SSHKeyAddedActivityData +from engagementmanager.utils.vvp_exceptions import VvpBadRequest +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.views_helper import checkAndModifyIfSSHNextStepExist, \ + getFirstEngByUser, addUsersToEngTeam +from engagementmanager.vm_integration import vm_client + + +class UserService(BaseSvc): + + def validate_ssh_key(self, sshkey): + ssh = SSHKey(sshkey) + + try: + ssh.parse() + except Exception as e: + msg = """ssh provided by the user is invalid, type of exception: """ + \ + str(e) + self.logger.error(msg) + msg = "Updating SSH Key failed due to invalid key." + raise VvpBadRequest(msg) + + # remove comment from ssh key + # ssh.comment returns comment attached to key + if ssh.comment != None: + striped_key = sshkey.replace(ssh.comment, '').strip() + else: + striped_key = sshkey.strip() + try: + user_with_ssh = IceUserProfile.objects.get( + ssh_public_key__startswith=striped_key) + except IceUserProfile.DoesNotExist: + return True + except Exception as e: + self.logger.error( + "Exception thrown while looking for ssh - %s.", e) + msg = "Updating SSH Key failed." + raise Exception(msg) + else: + self.logger.debug( + "SSH key already taken by another user - uuid: %s", user_with_ssh.uuid) + msg = "Updating SSH Key failed due to invalid key." + raise VvpBadRequest(msg) + + def setSSH(self, user, ssh, action): + user.ssh_public_key = ssh + checkAndModifyIfSSHNextStepExist(user) + eng = getFirstEngByUser(user) + + activity_data = SSHKeyAddedActivityData(action, eng, user) + bus_service.send_message(ActivityEventMessage(activity_data)) + + def get_el_list(self): + el_role = Role.objects.get(name='el') + engagement_leads_users = IceUserProfile.objects.filter(role=el_role) + return SuperThinIceUserProfileModelSerializerForSignals(engagement_leads_users, many=True).data + + def get_user_by_email(self, email): + UserModel = get_user_model() + try: + user = UserModel._default_manager.get(email=email) + except UserModel.DoesNotExist: + return None + return user + + def addUserToEngAndFireProvisionVfSig(self, user_profile, inviteObj): + addUsersToEngTeam(inviteObj.engagement_uuid, [user_profile]) + vfObj = VF.objects.get(engagement__uuid=inviteObj.engagement_uuid) + vm_client.fire_event_in_bg('send_provision_new_vf_event', vfObj) + + def get_user_rgwa_secret(self): + secret = request_data_mgr.get_user().rgwa_secret_key + decoded_key = CryptographyText.decrypt(secret) + return decoded_key diff --git a/django/engagementmanager/service/vf_service.py b/django/engagementmanager/service/vf_service.py new file mode 100755 index 0000000..aa3a9d3 --- /dev/null +++ b/django/engagementmanager/service/vf_service.py @@ -0,0 +1,47 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.models import VF +from engagementmanager.service.base_service import BaseSvc + + +class VFSvc(BaseSvc): + + def get_vf_version(self, vf_uuid): + vf = VF.objects.get(uuid=vf_uuid) + return vf.version diff --git a/django/engagementmanager/service/vfc_service.py b/django/engagementmanager/service/vfc_service.py new file mode 100755 index 0000000..341cfc1 --- /dev/null +++ b/django/engagementmanager/service/vfc_service.py @@ -0,0 +1,112 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import bleach + +from engagementmanager.models import VFC, IceUserProfile, VF, Vendor +from engagementmanager.service.base_service import BaseSvc + + +class VFCSvc(BaseSvc): + + def create_vfc(self, data): + msg = "OK" + vf = None + vfc = None + user = None + company = None + duplicateNames = [] + duplicate = False + many = True + dict = {} + # Iterate through all the VFCs that are received from the user, if there's duplication -> check the VF, if it is the same ->duplicate = True + # If there's a duplication and the other VFCs trying to be created are not + # duplicated -> Many = True -> they would be successfully created any way + for i in range(len(data['vfcs'])): + dict.update(data['vfcs'][i]) + # check if the VFC already exist (filter by name) + try: + vfc = VFC.objects.filter(name=dict['name'], external_ref_id=dict['external_ref_id']) + # if found VFC with same name and ref id + if (vfc.count() > 0): + for item in vfc: + if (item.vf.uuid == data['vf_uuid']): + if (not duplicate): + duplicate = True + duplicateNames.append(dict['name']) + # if found a similar VFC with name and ref_id, but VF is different ( + # cannot use else, and raise, since the for has to check all vfcs that + # match - for example, 2 VFs with same vfc) + if not duplicate: + raise VFC.DoesNotExist + # didn't find any vfc with same name and ref_id + else: + raise VFC.DoesNotExist + # If the VFC Does not exist, then continue as usual and create it. + except VFC.DoesNotExist: + many = True # not used, unless there's a duplicate as well, just a helper + + user = IceUserProfile.objects.get(email=data['creator']['email']) + vf = VF.objects.get(uuid=data['vf_uuid']) + # Check if the company that the user entered already exist. + try: + company = Vendor.objects.get(name=dict['company']) + except Vendor.DoesNotExist: + company = Vendor.objects.create(name=dict['company'], public=False) + company.save() + # create the VFC + vfc = VFC.objects.create(name=dict['name'], company=company, vf=vf, + creator=user, external_ref_id=dict['external_ref_id']) + if 'ice_mandated' in dict: + vfc.ice_mandated = dict['ice_mandated'] + vfc.save() + + dict = {} + if duplicate and many: + num = 1 + for vfc_name in duplicateNames: + msg = msg + str(num) + ". The VFC " + vfc_name + \ + " already exist, the VF that it is related to is: " + item.vf.name + "\n" + num += 1 + msg = msg + "\nThe other VFCs were created succesfully\n" + self.logger.error(msg) + msg = bleach.clean(msg, tags=['a', 'b']) + return msg + + def delete_vfc(self, vfc_uuid): + VFC.objects.get(uuid=vfc_uuid).delete() diff --git a/django/engagementmanager/slack_client/__init__.py b/django/engagementmanager/slack_client/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/slack_client/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/slack_client/api.py b/django/engagementmanager/slack_client/api.py new file mode 100755 index 0000000..f006322 --- /dev/null +++ b/django/engagementmanager/slack_client/api.py @@ -0,0 +1,212 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import concurrent.futures +from django.conf import settings +from slacker import Slacker, Error +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() +executor = concurrent.futures.ThreadPoolExecutor(max_workers=4) + + +class SlackClient(object): + """ + ICE Slack API Client + """ + + def __init__(self): + """ + Ice Slack client constructor -> + """ + super(SlackClient, self).__init__() + + # create the slack client + self.client = None + if settings.SLACK_API_TOKEN is not None and settings.SLACK_API_TOKEN != "": + try: + self.client = Slacker(settings.SLACK_API_TOKEN) + except Exception as exception: + logger.error('Unknown error while creating the a slack client: ' + str(exception)) + + # post a message via the Slack API + def trigger_slack_chat_post_message(self, to, message): + """ + # Syntax for chat.post_message + def post_message(self, channel, text=None, username=None, as_user=None, + parse=None, link_names=None, attachments=None, + unfurl_links=None, unfurl_media=None, icon_url=None, + icon_emoji=None): + """ + try: + # Send a message to a channel or a user + response = self.client.chat.post_message(to, message) + except Error as e: + logger.error('Invalid Slack API token was provided: ' + str(e)) + except Exception as exception: + logger.error('Unknown error while posting a message to Slack: ' + str(exception)) + + # asynchronously post a message + def post_message(self, to, message): + """ + Post a message to a channel or user + """ + if self.client is None: + return None + + if to and message: + logger.debug('Trigger Slack API - chat.post_message') + future = executor.submit(self.trigger_slack_chat_post_message, to, message) + logger.debug('Continuing after triggering the Slack API - chat.post_message') + + # send slack message to the engagement channel + def update_engagement_channel(self, message, notify_channel=False): + prefix = '' + if notify_channel: + prefix = '<!channel> ' + if settings.ENGAGEMENTS_CHANNEL: + # post to the engagement channel + self.post_message(settings.ENGAGEMENTS_CHANNEL, prefix + message) + + # send slack message to the devops channel + def update_devops_channel(self, message, notify_channel=False): + prefix = '' + if notify_channel: + prefix = '<!channel> ' + if settings.DEVOPS_CHANNEL: + # post to the engagement channel + self.post_message(settings.DEVOPS_CHANNEL, prefix + message) + + # send slack message to a user + def send_message_to_user(self, user, message): + # send Slack message to the newly assigned user + if user and user.slack_handle: + self.post_message('@' + user.slack_handle, message) + + # update reviewer or peer reviewer when a new engagement is created + def update_reviewer_or_peer_reviewer(self, engagement_manual_id, vf_name, user, old_user, notification_type='reviewer'): + # construct the Slack messages + user_message = 'You have been assigned as the _{}_ for the engagement _{}: {}_. '.format( + notification_type, engagement_manual_id, vf_name) + old_user_message_postfix = 'The assigned _{}_ is now _{}_.'.format(notification_type, user.full_name) + + user_message_postfix = "" + old_user_message = "" + if old_user is not None: + user_message_postfix = 'The previously assigned _{}_ was _{}_ in case you need to reach out for questions.'.format( + notification_type, old_user.full_name) + old_user_message = 'You are no longer the assigned _{}_ for the engagement _{}: {}_. '.format( + notification_type, engagement_manual_id, vf_name) + + # send Slack messages + self.send_message_to_user(user, user_message + user_message_postfix) + self.send_message_to_user(old_user, old_user_message + old_user_message_postfix) + + # update the engagement channel when a new engagement is created + def update_engagement_channel_for_new_engagement(self, engagement_manual_id, vf_name, reviewer, peer_reviewer, creator): + new_engagement_message = '_{}_ created a new engagement _{}: {}_. _{}_ was assigned as the reviewer and _{}_ as the peer reviewer'.format( + creator.full_name, engagement_manual_id, vf_name, reviewer.full_name, peer_reviewer.full_name) + self.update_engagement_channel(new_engagement_message, True) + + # update reviewer, peer reviewer and the engagement channel when a new engagement is created + def send_slack_notifications_for_new_engagement(self, engagement_manual_id, vf_name, reviewer, peer_reviewer, creator): + self.update_reviewer_or_peer_reviewer(engagement_manual_id, vf_name, reviewer, None, 'reviewer') + self.update_reviewer_or_peer_reviewer(engagement_manual_id, vf_name, peer_reviewer, None, 'peer reviewer') + self.update_engagement_channel_for_new_engagement( + engagement_manual_id, vf_name, reviewer, peer_reviewer, creator) + + def send_slack_notifications_for_new_feedback(self, feedback, user): + new_feedback_message = 'Created a new Feedback by {} Description : {}.'.format( + user.full_name, feedback.description) + self.update_engagement_channel(new_feedback_message, True) + self.update_devops_channel(new_feedback_message, True) + + # update the engagement channel when the stage is changed for an engagement + def update_for_change_of_the_engagement_stage(self, engagement_manual_id, vf_name, stage): + change_engagement_stage_message = 'The engagement _{}: {}_ was moved to the _{}_ stage.'.format( + engagement_manual_id, vf_name, stage) + self.update_engagement_channel(change_engagement_stage_message) + + # update the engagement channel when an engagement is archived + def update_for_archived_engagement(self, engagement_manual_id, vf_name, reason): + archived_engagement_message = 'The engagement _{}: {}_ was archived because of this reason: _{}_.'.format( + engagement_manual_id, vf_name, reason) + self.update_engagement_channel(archived_engagement_message) + + # update the reviewer and peer reviewer when the git repository is updated + def send_notifications_on_git_push(self, engagement_manual_id, vf_name, reviewer, peer_reviewer, committed_files): + str_committed_files = "The following files was added or changed as part of the commit:\n\n- %s" % '\n- '.join( + committed_files) + message = 'The Git repository for the engagement _{}: {}_ in which you are assigned as a _{}_ was updated. ' + \ + str_committed_files + self.send_message_to_user(reviewer, message.format(engagement_manual_id, vf_name, 'reviewer')) + self.send_message_to_user(peer_reviewer, message.format(engagement_manual_id, vf_name, 'peer_reviewer')) + + # update the reviewer when the automation phase is completed for a checklist + def send_notification_to_reviewer_when_automation_completes(self, engagement_manual_id, vf_name, reviewer, checklist_name): + message = 'The automation phase completed for the checklist _{}_ under the engagement _{}: {}_. You can now start your review of it.' + self.send_message_to_user(reviewer, message.format(checklist_name, engagement_manual_id, vf_name)) + + # update the peer reviewer when the review phase is completed for a checklist + def send_notification_to_peer_reviewer_when_the_review_completes(self, engagement_manual_id, vf_name, reviewer, peer_reviewer, checklist_name): + message = 'The review phase was completed by _{}_ for the checklist _{}_ under the engagement _{}: {}_. You can now start your peer review of it.' + self.send_message_to_user(peer_reviewer, message.format( + reviewer.full_name, checklist_name, engagement_manual_id, vf_name)) + + # update the admins when the review and peer reviews have been completed for a checklist + def send_notification_to_admins_when_the_peer_review_completes(self, engagement_manual_id, vf_name, reviewer, peer_reviewer, admins, checklist_name): + message = 'The manual reviews have been completed by the reviewer _{}_ and peer reviewer _{}_ for the checklist _{}_ under the engagement _{}: {}_. It is now waiting for an approval by you or any other admin.' + for admin in admins: + self.send_message_to_user(admin, message.format( + reviewer.full_name, peer_reviewer.full_name, checklist_name, engagement_manual_id, vf_name)) + + # update reviewer when a checklist is approved + def send_notification_to_reviewer_when_approved(self, engagement_manual_id, vf_name, reviewer, checklist_name): + message = 'The checklist _{}_ under the engagement _{}: {}_ is now approved. You can now hand off the artifacts and close out the checklist.' + self.send_message_to_user(reviewer, message.format(checklist_name, engagement_manual_id, vf_name)) + + # update reviewer, peer reviewer and admins when a checklist is closed + def send_notifications_when_closed(self, engagement_manual_id, vf_name, reviewer, peer_reviewer, admins, checklist_name): + message = 'The checklist _{}_ under the engagement _{}: {}_ has now been closed and all the asssociated artifacts are validated. The reviewer was _{}_ and the peer reviewer was _{}_.' + self.send_message_to_user(reviewer, message.format(checklist_name, engagement_manual_id, + vf_name, reviewer.full_name, peer_reviewer.full_name)) + self.send_message_to_user(peer_reviewer, message.format( + checklist_name, engagement_manual_id, vf_name, reviewer.full_name, peer_reviewer.full_name)) + for admin in admins: + self.send_message_to_user(admin, message.format(checklist_name, engagement_manual_id, + vf_name, reviewer.full_name, peer_reviewer.full_name)) diff --git a/django/engagementmanager/sql-scripts/generate_excel_overview_sheet_procedure.sql b/django/engagementmanager/sql-scripts/generate_excel_overview_sheet_procedure.sql new file mode 100755 index 0000000..79925be --- /dev/null +++ b/django/engagementmanager/sql-scripts/generate_excel_overview_sheet_procedure.sql @@ -0,0 +1,203 @@ +-- +-- ============LICENSE_START========================================== +-- org.onap.vvp/engagementmgr +-- =================================================================== +-- Copyright C 2017 AT&T Intellectual Property. All rights reserved. +-- =================================================================== +-- +-- Unless otherwise specified, all software contained herein is licensed +-- under the Apache License, Version 2.0 (the "License"); +-- you may not use this software except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- +-- +-- Unless otherwise specified, all documentation contained herein is licensed +-- under the Creative Commons License, Attribution 4.0 Intl. (the "License"); +-- you may not use this documentation except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- https://creativecommons.org/licenses/by/4.0/ +-- +-- Unless required by applicable law or agreed to in writing, documentation +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- ============LICENSE_END============================================ +-- +-- ECOMP is a trademark and service mark of AT&T Intellectual Property. +CREATE OR REPLACE FUNCTION generate_excel_overview_sheet(stage TEXT, keyword TEXT) +RETURNS TABLE (name VARCHAR(200), + active_engagements INTEGER, + active_vfc_sum INTEGER, + intake_engagements INTEGER, + intake_vfc_sum INTEGER, + completed_engagements INTEGER, + completed_vfc_sum INTEGER, + total_engagements INTEGER, + total_vfc_sum INTEGER) AS $res$ +BEGIN + -- temp tables declarations: + CREATE TEMP TABLE result + ( + name VARCHAR(200), + active_engagements INTEGER, + active_vfc_sum INTEGER, + intake_engagements INTEGER, + intake_vfc_sum INTEGER, + completed_engagements INTEGER, + completed_vfc_sum INTEGER, + total_engagements INTEGER, + total_vfc_sum INTEGER + ) ON COMMIT DROP; + + CREATE TEMP TABLE filters + ( + name VARCHAR(200), + value VARCHAR(200) + ) ON COMMIT DROP; + + CREATE TEMP TABLE deployment_targets + ( + deployment_target_uuid VARCHAR(200), + deployment_targets INTEGER + ) ON COMMIT DROP; + + CREATE TEMP TABLE engagement_stages + ( + engagement_stage VARCHAR(200), + total INTEGER + ) ON COMMIT DROP; + + CREATE TEMP TABLE virtual_functions_componenets + ( + name VARCHAR(200), + engagement_stage VARCHAR(200) + ) ON COMMIT DROP; + + CREATE TEMP TABLE ecomp_releases + ( + ecomp_release_uuid VARCHAR(200), + ecomp_release_name VARCHAR(200) + ) ON COMMIT DROP; + + -- Handling filters + IF $1 = 'All' OR $1 = 'all' OR $1 IS NULL THEN stage := ''; ELSE stage := $1; END IF; + INSERT INTO filters VALUES('stage', stage); + IF $2 IS NULL THEN keyword := ''; ELSE keyword := $2; END IF; + INSERT INTO filters VALUES('keyword', keyword); + + -- handling AIC (deployment targets) rows: + INSERT INTO deployment_targets + SELECT deployment_target_id, COUNT(deployment_target_id) AS total FROM ice_vf GROUP BY deployment_target_id; + + -- Itearting throght each deployment: + DO $$ + DECLARE + deployment record; + vf record; + ecomp record; + stage TEXT; + keyword TEXT; + BEGIN + -- Get the filters from outside: + SELECT value FROM filters WHERE name = 'stage' LIMIT 1 INTO stage; + SELECT value FROM filters WHERE name = 'keyword' LIMIT 1 INTO keyword; + FOR deployment IN SELECT * FROM deployment_targets LOOP + INSERT INTO engagement_stages + SELECT ice_engagement.engagement_stage, COUNT(ice_engagement.engagement_stage) + FROM ice_vf LEFT JOIN ice_engagement ON engagement_id = ice_engagement.uuid + WHERE ice_vf.deployment_target_id = deployment.deployment_target_uuid + AND ice_engagement.engagement_stage LIKE '%' || stage || '%' -- stage param filtering + AND (ice_engagement.engagement_manual_id LIKE '%' || keyword || '%' OR ice_vf.name LIKE '%' || keyword || '%') -- keyword param filtering + AND ice_engagement.engagement_stage IN ('Active', 'Intake', 'Completed') + GROUP BY ice_engagement.engagement_stage; + + INSERT INTO virtual_functions_componenets + SELECT ice_vfc.name, ice_engagement.engagement_stage + FROM ice_vfc LEFT JOIN ice_vf ON ice_vfc.vf_id = ice_vf.uuid + LEFT JOIN ice_engagement ON ice_vf.engagement_id = ice_engagement.uuid + WHERE ice_vf.deployment_target_id = deployment.deployment_target_uuid + AND ice_engagement.engagement_stage LIKE '%' || stage || '%' -- stage param filtering + AND (ice_engagement.engagement_manual_id LIKE '%' || keyword || '%' OR ice_vf.name LIKE '%' || keyword || '%' OR ice_vfc.name LIKE '%' || keyword || '%') -- keyword param filtering + AND ice_engagement.engagement_stage IN ('Active', 'Intake', 'Completed'); + + --Insert the AIC row with its statistics: + INSERT INTO result VALUES + ((SELECT version FROM ice_deployment_target WHERE uuid = deployment.deployment_target_uuid LIMIT 1), + (SELECT total FROM engagement_stages where engagement_stage = 'Active' LIMIT 1), + (SELECT COUNT(*) FROM virtual_functions_componenets WHERE engagement_stage = 'Active'), + (SELECT total FROM engagement_stages where engagement_stage = 'Intake' LIMIT 1), + (SELECT COUNT(*) FROM virtual_functions_componenets WHERE engagement_stage = 'Intake'), + (SELECT total FROM engagement_stages where engagement_stage = 'Completed' LIMIT 1), + (SELECT COUNT(*) FROM virtual_functions_componenets WHERE engagement_stage = 'Completed'), + (SELECT SUM(total) FROM engagement_stages), + (SELECT COUNT(*) FROM virtual_functions_componenets) + ); + + --****************************************************************************************************** + --Handling the ecomp release rows: + INSERT INTO ecomp_releases + SELECT DISTINCT ice_ecomp_release.uuid, ice_ecomp_release.name + FROM ice_vf LEFT JOIN ice_ecomp_release ON ice_ecomp_release.uuid = ice_vf.ecomp_release_id + WHERE ice_vf.deployment_target_id = deployment.deployment_target_uuid; + + FOR ecomp IN SELECT * FROM ecomp_releases LOOP + --empty the temp tables: + DELETE FROM virtual_functions_componenets; + DELETE FROM engagement_stages; + + INSERT INTO engagement_stages + SELECT ice_engagement.engagement_stage, COUNT(ice_engagement.engagement_stage) + FROM ice_vf LEFT JOIN ice_engagement ON engagement_id = ice_engagement.uuid + WHERE ice_vf.deployment_target_id = deployment.deployment_target_uuid AND ice_vf.ecomp_release_id = ecomp.ecomp_release_uuid + AND ice_engagement.engagement_stage LIKE '%' || stage || '%'--stage param filtering + AND (ice_engagement.engagement_manual_id LIKE '%' || keyword || '%' OR ice_vf.name LIKE '%' || keyword || '%') --keyword param filtering + AND ice_engagement.engagement_stage IN ('Active', 'Intake', 'Completed') + GROUP BY ice_engagement.engagement_stage; + + INSERT INTO virtual_functions_componenets + SELECT ice_vfc.name, ice_engagement.engagement_stage + FROM ice_vfc LEFT JOIN ice_vf ON ice_vfc.vf_id = ice_vf.uuid + LEFT JOIN ice_engagement ON ice_vf.engagement_id = ice_engagement.uuid + WHERE ice_vf.deployment_target_id = deployment.deployment_target_uuid AND ice_vf.ecomp_release_id = ecomp.ecomp_release_uuid + AND ice_engagement.engagement_stage LIKE '%' || stage || '%'--stage param filtering + AND (ice_engagement.engagement_manual_id LIKE '%' || keyword || '%' OR ice_vf.name LIKE '%' || keyword || '%' OR ice_vfc.name LIKE '%' || keyword || '%') -- keyword param filtering + AND ice_engagement.engagement_stage IN ('Active', 'Intake', 'Completed'); + + --Insert the ecomp release row with its statistics: + INSERT INTO result VALUES + (' >>' || ecomp.ecomp_release_name, + (SELECT total FROM engagement_stages where engagement_stage = 'Active' LIMIT 1), + (SELECT COUNT(*) FROM virtual_functions_componenets WHERE engagement_stage = 'Active'), + (SELECT total FROM engagement_stages where engagement_stage = 'Intake' LIMIT 1), + (SELECT COUNT(*) FROM virtual_functions_componenets WHERE engagement_stage = 'Intake'), + (SELECT total FROM engagement_stages where engagement_stage = 'Completed' LIMIT 1), + (SELECT COUNT(*) FROM virtual_functions_componenets WHERE engagement_stage = 'Completed'), + (SELECT SUM(total) FROM engagement_stages), + (SELECT COUNT(*) FROM virtual_functions_componenets) + ); + END LOOP; + --****************************************************************************************************** + + --empty the temp tables: + DELETE FROM virtual_functions_componenets; + DELETE FROM engagement_stages; + DELETE FROM ecomp_releases; + END LOOP; + END $$; + + RETURN QUERY SELECT * FROM result; +END; +$res$ +LANGUAGE 'plpgsql' VOLATILE; diff --git a/django/engagementmanager/templatetags/__init__.py b/django/engagementmanager/templatetags/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/templatetags/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/templatetags/vvptags.py b/django/engagementmanager/templatetags/vvptags.py new file mode 100755 index 0000000..1a6a0ee --- /dev/null +++ b/django/engagementmanager/templatetags/vvptags.py @@ -0,0 +1,48 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.template import Library + +from engagementmanager.utils.constants import TemplatesConstants + +register = Library() + + +@register.simple_tag +def get_templates_constants(name): + return TemplatesConstants.context[name] diff --git a/django/engagementmanager/tests/__init__.py b/django/engagementmanager/tests/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/tests/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/tests/test_access_credentials.py b/django/engagementmanager/tests/test_access_credentials.py new file mode 100755 index 0000000..73d427c --- /dev/null +++ b/django/engagementmanager/tests/test_access_credentials.py @@ -0,0 +1,175 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.tests.test_base_entity import TestBaseEntity +import json +from boto.s3.connection import S3Connection, OrdinaryCallingFormat +from django.conf import settings +from wheel.signatures import assertTrue +from django.utils import timezone +from engagementmanager.utils.constants import Constants +from engagementmanager.vm_integration import vm_client +from validationmanager.rados.rgwa_client import RGWAClient +from validationmanager.tests.test_rgwa_client_factory import TestRGWAClientFactory + + +class ActivateTestCase(TestBaseEntity): + + def childSetup(self): # Variables to use in this class. + self.s3_host = '10.252.0.21' # settings.AWS_S3_HOST + self.s3_port = 8080 # settings.AWS_S3_PORT + + self.urlStr = self.urlPrefix + "signup/" + self.createDefaultRoles() + uuid, vendor = self.creator.createVendor(Constants.service_provider_company_name) + self.activation_token_time = timezone.now() + self.activation_token_time = self.activation_token_time.replace( + 2012, 1, 2, 13, 48, 25) + print("This is the time that is going to be added to expiredTokenUser: " + + str(self.activation_token_time)) + self.user = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + self.new_user = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user.uuid)) + print('Full Name: ' + self.user.full_name) + print('-----------------------------------------------------') + self.params = '{"company":"' + str(self.user.company) + '","full_name":"' + self.user.full_name + '","email":"' + self.user.email + '","phone_number":"' + self.user.phone_number + \ + '","password":"' + self.user.user.password + '","regular_email_updates":"' + \ + str(self.user.regular_email_updates) + \ + '","is_service_provider_contact":"' + str(self.user.is_service_provider_contact) + '"}' + self.userToken = self.loginAndCreateSessionToken(self.user) + self.new_user_token = self.loginAndCreateSessionToken(self.new_user) + + def test_validate_rgwauser_created_after_Activation(self): + if settings.IS_SIGNAL_ENABLED: + vm_client.fire_event_in_bg( + 'send_create_user_in_rgwa_event', self.user) + rgwa = TestRGWAClientFactory.admin() + rgwa_user = rgwa.get_user(self.user.full_name) + if rgwa_user is None: + print("Test Failed!") + else: + access_key = rgwa_user['access_key'] + print("######access_key#################= ", access_key) + secret_key = rgwa_user['secret_key'] + print("######secret_key#################= ", secret_key) + self.assertTrue(access_key and secret_key != None) + print("#################################") + print("Test PASS!") + self.printTestName("Test ended") + + +# Whenever a new user is configured, we should create a RadosGW user for them. +# If unspecified, the access keys are generated on the server and returned here +# in the response. + def testCreateAndGetRgwaUser(self): + if settings.IS_SIGNAL_ENABLED: + base_url = 'http://{S3_HOST}:{S3_PORT}/admin'.format( + S3_HOST=self.s3_host, # settings.AWS_S3_HOST, + S3_PORT=self.s3_port, # settings.AWS_S3_PORT, + ) + admin_conn = RGWAClient(base_url) + print("base_url=" + base_url) + print("S3_HOST = " + self.s3_host) + print("s3_port =" + str(self.s3_port)) + print("admin_conn= ", admin_conn) + username = self.randomGenerator("randomString") + print("username", username) + new_user = admin_conn.create_user( + uid=username, display_name='User "%s"' % username) + print("new_user = " + str(new_user)) + self.assertTrue(new_user['user_id'] != None) + get_user = admin_conn.get_user(new_user['user_id']) + self.assertTrue(new_user['user_id'] == get_user['user_id']) + + def testCreateAndGetRgwaBucket(self): + if settings.IS_SIGNAL_ENABLED: + s3aws_access_key_id = settings.AWS_ACCESS_KEY_ID + s3aws_secret_access_key = settings.AWS_SECRET_ACCESS_KEY + print("s3aws_access_key_id=" + s3aws_access_key_id) + print("s3aws_secret_access_key=" + s3aws_secret_access_key) + print("S3_HOST = " + self.s3_host) + print("s3_port =" + str(self.s3_port)) + + boto_conn = S3Connection(host=self.s3_host, + port=self.s3_port, + aws_access_key_id=s3aws_access_key_id, + aws_secret_access_key=s3aws_secret_access_key, + calling_format=OrdinaryCallingFormat(), + is_secure=False, + ) + boto_conn.num_retries = 0 + bucketname = self.randomGenerator("randomString").lower() + new_bucket = boto_conn.create_bucket(bucketname) + assertTrue(new_bucket != None) + print("new_bucket = " + str(new_bucket)) + bucket = boto_conn.get_bucket(bucketname) + print("bucket = " + str(bucket)) + bucket_acl = bucket.get_acl() + print("bucket_acl = " + str(bucket_acl)) + + def testGetSecretKey(self): + vm_client.send_create_user_in_rgwa_event(self.user) + urlStr = self.urlPrefix + 'users/account/rgwa/' + print("urlStr of get secret key",urlStr) + self.printTestName("testGetSecretKey [Start]") + response = self.c.get(urlStr, data={}, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.userToken}) + print('Got response : ' + str(response.status_code)) + dict_response = json.loads(response.content) + print("api response",dict_response) + self.assertTrue(dict_response["rgwa_secret_key"] is not None) + self.printTestName("testGetSecretKey [End]") + + def testNegativeGetSecretKeyInvalidToken(self): + vm_client.send_create_user_in_rgwa_event(self.user) + urlStr = self.urlPrefix + 'users/account/rgwa/' + print("urlStr of get secret key",urlStr) + self.printTestName("testGetSecretKey [Start]") + response = self.c.get(urlStr, data={}, content_type='application/json', + **{'HTTP_AUTHORIZATION': 'token' + self.new_user_token}) + print('Got response : ' + str(response.status_code)) + dict_response = json.loads(response.content) + print("api response",dict_response) + self.assertTrue(dict_response[ + "detail"] == 'You must authenticate in order to ' + + 'perform this action: Authentication credentials were not provided.') + self.printTestName("testGetSecretKey [End]") diff --git a/django/engagementmanager/tests/test_activation.py b/django/engagementmanager/tests/test_activation.py new file mode 100755 index 0000000..a845373 --- /dev/null +++ b/django/engagementmanager/tests/test_activation.py @@ -0,0 +1,173 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.utils import timezone + +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants + + +class ActivateTestCase(TestBaseEntity): + + def childSetup(self): # Variables to use in this class. + self.urlStr = self.urlPrefix + "signup/" + self.createDefaultRoles() + uuid, vendor = self.creator.createVendor(Constants.service_provider_company_name) + self.activation_token_time = timezone.now() + self.activation_token_time = self.activation_token_time.replace(2012, 1, 2, 13, 48, 25) + print("This is the time that is going to be added to expiredTokenUser: " + str(self.activation_token_time)) + self.user = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, False) + self.expiredTokenUser = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, False, activation_token_create_time=self.activation_token_time) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user.uuid)) + print('Full Name: ' + self.user.full_name) + print('-----------------------------------------------------') + self.params = '{"company":"' + str(self.user.company) + '","full_name":"' + self.user.full_name + '","email":"' + self.user.email + '","phone_number":"' + self.user.phone_number + \ + '","password":"' + self.user.user.password + '","regular_email_updates":"' + \ + str(self.user.regular_email_updates) + '","is_service_provider_contact":"' + str(self.user.is_service_provider_contact) + '"}' + + def testActivation(self): + print("\n\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + print(" Test started: user activation") + print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + for a in range(2): + print("###############################################") + print(" Before activation, Current User's activation mode: " + str(self.user.user.is_active)) + for a in range(2): + print("###############################################") + user_uuid = self.user.uuid + print(self.urlPrefix + 'activate/' + str(user_uuid) + '/' + str(self.user.user.activation_token)) + print("Activating through the activate_user function: (simulating a GET request)") + response = self.c.get(self.urlPrefix + 'activate/' + str(user_uuid) + + '/' + str(self.user.user.activation_token)) + print("Response: " + str(response.status_code)) + self.user.refresh_from_db() + for a in range(5): + print("******") + for a in range(2): + print("###############################################") + print(" Current User's activation mode: " + str(self.user.user.is_active)) + for a in range(2): + print("###############################################") + print("Current User's activation mode: " + str(self.user.user.is_active)) + if (self.user.user.is_active != True): + for a in range(2): + print("###############################################") + print(" User's activation failed: is_active != True..") + for a in range(2): + print("###############################################") + else: + for a in range(2): + print("#################################") + print(" User's is activated ") + for a in range(2): + print("#################################") + self.printTestName("Test ended") + + def testExpiredTokenActivation(self): + print("\n\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + print("Negative test started: Expired token activation") + print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + for a in range(2): + print("###############################################") + print("Current User's activation mode: " + str(self.user.user.is_active)) + for a in range(2): + print("###############################################") + + urlStrToGET = self.urlPrefix + "users/" + user_uuid = self.expiredTokenUser.uuid + print("\n\nA user with was pre-initiated with old token creation time : 2012-01-02 13:48:25.299000+00:00\n\n") + response = self.c.get(self.urlPrefix + 'activate/' + str(user_uuid) + '/' + + str(self.expiredTokenUser.user.activation_token)) + self.user.refresh_from_db() + for a in range(2): + print("###############################################") + print(" Current User's activation mode: " + str(self.expiredTokenUser.user.is_active)) + for a in range(2): + print("###############################################") + print("\n\n") + if (self.expiredTokenUser.user.activation_token != True): + for a in range(2): + print("###############################################") + print("Test Success!") + for a in range(2): + print("###############################################") + else: + for a in range(2): + print("###############################################") + print("Test Failed!") + for a in range(2): + print("###############################################") + + def testUnMatchingTokenActivation(self): + print("\n\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + print("Negative test started: Un-matching token activation test") + print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + for a in range(2): + print("###############################################") + print("Current User's activation mode: " + str(self.user.user.is_active)) + for a in range(2): + print("###############################################") + + urlStrToGET = self.urlPrefix + "users/" + user_uuid = self.expiredTokenUser.uuid + print("\n\n Trying to activate a user with an unmatching token") + response = self.c.get(self.urlPrefix + 'activate/' + str(self.user.uuid) + + '/' + str(self.expiredTokenUser.user.activation_token)) + self.user.refresh_from_db() + for a in range(2): + print("###############################################") + print(" Current User's activation mode: " + str(self.expiredTokenUser.user.is_active)) + for a in range(2): + print("###############################################") + print("\n\n") + if (self.expiredTokenUser.user.activation_token != True): + for a in range(2): + print("###############################################") + print("Test Success!") + for a in range(2): + print("###############################################") + else: + for a in range(2): + print("###############################################") + print("Test Failed!") + for a in range(2): + print("###############################################") diff --git a/django/engagementmanager/tests/test_activities.py b/django/engagementmanager/tests/test_activities.py new file mode 100755 index 0000000..9e83e9f --- /dev/null +++ b/django/engagementmanager/tests/test_activities.py @@ -0,0 +1,125 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.bus.messages.activity_event_message import ActivityEventMessage +from engagementmanager.models import Vendor +from engagementmanager.utils.activities_data import UserJoinedEngagementActivityData +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.apps import bus_service +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class ActivityTestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + + self.createDefaultRoles() + # Create a user with role el + vendor = Vendor.objects.get(name=Constants.service_provider_company_name) + self.el_user = self.creator.createUser(vendor, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + vendor = Vendor.objects.get(name='Other') + self.user = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + self.pruser = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + + # Create an Engagement with team + self.engagement = self.creator.createEngagement(self.randomGenerator( + "randomString"), self.randomGenerator("randomString"), None) + self.engagement.engagement_team.add(self.user, self.el_user) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.pruser + self.engagement.save() + + # Create a VF + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, vendor) + self.token = self.loginAndCreateSessionToken(self.user) + + def testCreateActivity(self): + urlStr = self.urlPrefix + 'engagement/${uuid}/activities/' + logger.debug("Starting Activity & notification creation test") + + logger.debug("Starting activity test: User joined") + vendor = Vendor.objects.get(name='Other') + randomUser = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + self.engagement.engagement_team.add(randomUser) + self.engagement.save() + + logger.debug( + "created a new user & added them to the engagement team, going to create the activity and consider it as a notification") + usersList = [] + usersList.append(randomUser) + activity_data = UserJoinedEngagementActivityData(self.vf, usersList, self.engagement) + bus_service.send_message(ActivityEventMessage(activity_data)) + logger.debug( + "activity & notification created successfully, please manually verify that an email was sent / MX server tried to send") + logger.debug("Ended activity test: User joined ") + + logger.debug("Starting pullActivities test") + response = self.c.get(urlStr.replace('${uuid}', str(self.engagement.uuid)), + **{'HTTP_AUTHORIZATION': "token " + self.token}) + content = response.content + status = response.status_code + logger.debug("Got response : " + str(status)) + logger.debug("Got content : " + str(content)) + if (status != 200): + logger.error("Got response : " + str(status) + " , wrong http response returned ") + self.assertEqual(response.status_code, 200) + logger.debug("Ended pullActivities test ") + + logger.debug("Starting activity test: delete user") + logger.debug("Verify that the 'User Joined' activity is deleted from the recent activities") + response = self.c.get(urlStr.replace('${uuid}', str(self.engagement.uuid)), + **{'HTTP_AUTHORIZATION': "token " + self.token}) + content = response.content + status = response.status_code + logger.debug("Got response : " + str(status)) + logger.debug("Got content : " + str(content)) + if (status != 200): + logger.error("Got response : " + str(status) + " , wrong http response returned ") + self.assertEqual(response.status_code, 200) + logger.debug("Ended activity test: delete user ") diff --git a/django/engagementmanager/tests/test_add_contact.py b/django/engagementmanager/tests/test_add_contact.py new file mode 100755 index 0000000..c1af553 --- /dev/null +++ b/django/engagementmanager/tests/test_add_contact.py @@ -0,0 +1,141 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import random +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.models import Vendor +from engagementmanager.utils.constants import Constants + + +class TestAddContactTestCase(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Other']) + + self.createDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator( + "main-vendor-email"), '55501000199', 'el user', self.el, True) + + self.inviter = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator( + "main-vendor-email"), '55501000199', 'inviter user', self.standard_user, True) + + self.reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator( + "main-vendor-email"), '55501000199', 'reviewer user', self.el, True) + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator( + "main-vendor-email"), '55501000199', 'peer-reviewer user', self.el, True) + # Create an Engagement with team + self.engagement = self.creator.createEngagement( + '123456789', 'Validation', None) + self.engagement.reviewer = self.reviewer + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.save() + self.engagement.engagement_team.add(self.inviter, self.el_user) + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement.uuid)) + print('-----------------------------------------------------') + + # Create a VF + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), self.engagement, + self.deploymentTarget, False, Vendor.objects.get(name='Other')) + + self.urlStr = self.urlPrefix + "add-contact/" + self.data = dict() + self.token = self.loginAndCreateSessionToken(self.el_user) + + def initBody(self): + self.data['company'] = Vendor.objects.get(name=Constants.service_provider_company_name).name + self.data['full_name'] = "full name" + self.data['email'] = self.randomGenerator("main-vendor-email") + self.data['phone_number'] = "12345" + + def addContact(self, expectedStatus=200): + self.contactData = json.dumps(self.data, ensure_ascii=False) + response = self.c.post(self.urlStr, self.contactData, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, expectedStatus) + return response + + def createContactUser(self): + self.contact = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.data['email'], + self.data['phone_number'], self.data['full_name'], self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.contact.uuid)) + print('Full Name: ' + self.contact.full_name) + print('-----------------------------------------------------') + + ### TESTS ### + + def testAddContactForNonExistingContact(self): + self.initBody() + self.data['eng_uuid'] = str(self.engagement.uuid) + self.data['email'] = self.randomGenerator("main-vendor-email") + self.addContact() + + def testAddContactForExistingContactAndEngUuid(self): + self.initBody() + self.createContactUser() + self.data['eng_uuid'] = str(self.engagement.uuid) + self.addContact(200) + + def testNegativeAddContactForNonExistingContact(self): + self.initBody() + self.data['eng_uuid'] = str(self.engagement.uuid) + self.data['email'] = None + print("Negative test: removing mandatory field email --> Should fail on 400") + self.addContact(400) + + def testNegativeAddContactForExistingContactAndFakeEngUUID(self): + self.initBody() + self.createContactUser() + self.data['eng_uuid'] = "FakeUuid" + print("Negative test: Non existing engagement UUID --> Should fail on 500") + self.addContact(401) diff --git a/django/engagementmanager/tests/test_add_feedback.py b/django/engagementmanager/tests/test_add_feedback.py new file mode 100755 index 0000000..33382aa --- /dev/null +++ b/django/engagementmanager/tests/test_add_feedback.py @@ -0,0 +1,105 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import random + +from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.models import Vendor +from engagementmanager.utils.constants import Constants +from engagementmanager.utils.request_data_mgr import request_data_mgr + + +class TestAddContactTestCase(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + self.reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), '55501000199', 'reviewer user', self.el, True) + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + # Create an Engagement with team + self.engagement = self.creator.createEngagement( + '123456789', 'Validation', None) + self.engagement.reviewer = self.reviewer + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.save() + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement.uuid)) + print('-----------------------------------------------------') + + # Create a VF + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), self.engagement, + self.deploymentTarget, False, Vendor.objects.get(name='Other')) + + self.urlStr = self.urlPrefix + "add-feedback/" + self.data = dict() + self.token = self.loginAndCreateSessionToken(self.reviewer) + + def initBody(self): + self.data['description'] = Vendor.objects.get( + name=Constants.service_provider_company_name).name + "ruslan gafiulin" + + def addFeedback(self, expectedStatus=HTTP_200_OK): + self.feedbackData = json.dumps(self.data, ensure_ascii=False) + response = self.c.post(self.urlStr, self.feedbackData, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, expectedStatus) + return response + + ### TESTS ### + + def testAddFeedbackForNonExistingContact(self): + self.initBody() + self.data['description'] = str(self.engagement.uuid) + self.data['eng_uuid'] = str(self.engagement.uuid) + self.addFeedback() + + def testNegativeAddFeedbackWithoutDescription(self): + self.initBody() + self.data['description'] = "" + self.data['eng_uuid'] = str(self.engagement.uuid) + self.addFeedback(HTTP_400_BAD_REQUEST) diff --git a/django/engagementmanager/tests/test_add_next_step_to_checklist.py b/django/engagementmanager/tests/test_add_next_step_to_checklist.py new file mode 100755 index 0000000..e88cddd --- /dev/null +++ b/django/engagementmanager/tests/test_add_next_step_to_checklist.py @@ -0,0 +1,157 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from uuid import uuid4 + +from rest_framework.status import HTTP_200_OK, HTTP_401_UNAUTHORIZED + +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants + + +class TestAddNextStepToChecklistTestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.vendor = Vendor.objects.get(name=Constants.service_provider_company_name) + self.createDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.el_user.uuid)) + print('Full Name: ' + self.el_user.full_name) + print('-----------------------------------------------------') + + # Create a user with role el + self.peer_reviewer_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.el_user.uuid)) + print('Full Name: ' + self.el_user.full_name) + print('-----------------------------------------------------') + + self.user2 = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), '55501000199', 'user', self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user2.uuid)) + print('Full Name: ' + self.user2.full_name) + print('-----------------------------------------------------') + + # Create an Engagement with team + self.engagement = self.creator.createEngagement('123456789', 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.engagement_team.add(self.el_user) + self.engagement.peer_reviewer = self.peer_reviewer_user + self.engagement.save() + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement.uuid)) + print('-----------------------------------------------------') + + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, self.vendor) + print('-----------------------------------------------------') + print('Created VF:') + print('UUID: ' + str(self.vf.uuid)) + print('-----------------------------------------------------') + + self.template = self.creator.createDefaultCheckListTemplate() + self.data = dict() + self.data['checkListName'] = "ice checklist for test" + self.data['checkListTemplateUuid'] = str(self.template.uuid) + self.data['checkListAssociatedFiles'] = [] + for i in range(0, 2): + self.data['checkListAssociatedFiles'].append("file" + str(i)) + self.token = self.loginAndCreateSessionToken(self.el_user) + datajson = json.dumps(self.data, ensure_ascii=False) + self.clUrlStr = self.urlPrefix + "engagement/@eng_uuid/checklist/new/" + self.checklist = self.c.post(self.clUrlStr.replace("@eng_uuid", str(self.engagement.uuid)), + datajson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + + self.urlStr = self.urlPrefix + "engagement/@eng_uuid/checklist/@checklist_uuid/nextstep/" + self.nextStepList = [] + + def initBody(self): + assigneesData = [str(self.el_user.uuid), str(self.user2.uuid)] + files = ["f1", "f2"] + self.data['assigneesUuids'] = assigneesData + self.data['description'] = "Good Bye Norma Jin" + self.data['files'] = files + self.data['duedate'] = "2016-12-01" + self.nextStepList.append(self.data) + + assigneesData = [str(self.el_user.uuid)] + files = ["f5"] + self.data['assigneesUuids'] = assigneesData + self.data['description'] = "Don't cry for me Argentina" + self.data['files'] = files + self.data['duedate'] = "2017-06-28" + self.nextStepList.append(self.data) + + def testAddNextStepForCheckListPositive(self): + self.initBody() + self.nextStepList = json.dumps(self.nextStepList, ensure_ascii=False) + self.urlStr = self.urlStr.replace("@checklist_uuid", json.loads(self.checklist.content)[ + 'uuid']).replace("@eng_uuid", str(self.engagement.uuid)) + response = self.c.post(self.urlStr, self.nextStepList, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + return response + + def testAddNextStepForCheckListNegative(self): + self.initBody() + self.nextStepList = json.dumps(self.nextStepList, ensure_ascii=False) + self.urlStr = self.urlStr.replace("@checklist_uuid", json.loads( + self.checklist.content)['uuid']).replace("@eng_uuid", str(uuid4())) + response = self.c.post(self.urlStr, self.nextStepList, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('------------------------------> Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + return response diff --git a/django/engagementmanager/tests/test_audit_log_and_decision_api.py b/django/engagementmanager/tests/test_audit_log_and_decision_api.py new file mode 100755 index 0000000..42395ae --- /dev/null +++ b/django/engagementmanager/tests/test_audit_log_and_decision_api.py @@ -0,0 +1,375 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from uuid import uuid4 +from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST,\ + HTTP_401_UNAUTHORIZED, HTTP_500_INTERNAL_SERVER_ERROR,\ + HTTP_405_METHOD_NOT_ALLOWED +from engagementmanager.models import Vendor, Checklist, ChecklistAuditLog, ChecklistDecision, ChecklistLineItem, ChecklistSection +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import CheckListLineType, CheckListDecisionValue, CheckListState, Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class AuditLogAndDecisionAPITest(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs', 'Other']) + self.createDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), '12323245435', 'el user', self.el, True) + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + # For negative tests + self.user = self.creator.createUser( + Vendor.objects.get(name=Constants.service_provider_company_name), + self.randomGenerator("main-vendor-email"), '12323245435', 'user', self.standard_user, True) + + self.template = self.creator.createDefaultCheckListTemplate() + self.engagement = self.creator.createEngagement( + uuid4(), 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.save() + self.engagement.engagement_team.add(self.el_user, self.user) + self.clbodydata = dict() + self.initCLBody() + self.auditdata = dict() + self.checklist = Checklist.objects.create(uuid=uuid4(), name=self.clbodydata['checkListName'], validation_cycle=1, associated_files=self.clbodydata[ + 'checkListAssociatedFiles'], engagement=self.engagement, template=self.template, creator=self.el_user, owner=self.el_user) + self.section = ChecklistSection.objects.create(uuid=uuid4(), name=self.randomGenerator("randomString"), weight=1.0, description=self.randomGenerator( + "randomString"), validation_instructions=self.randomGenerator("randomString"), template=self.template) + self.line_item = ChecklistLineItem.objects.create(uuid=uuid4(), name=self.randomGenerator("randomString"), weight=1.0, description=self.randomGenerator( + "randomString"), line_type=CheckListLineType.auto.name, validation_instructions=self.randomGenerator("randomString"), template=self.template, section=self.section) # @UndefinedVariable + self.decision = ChecklistDecision.objects.create( + uuid=uuid4(), checklist=self.checklist, template=self.template, lineitem=self.line_item) + self.section.save() + self.line_item.save() + self.decision.save() + self.checklist.save() + self.token = self.loginAndCreateSessionToken(self.user) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + + def initCLBody(self): + self.clbodydata['checkListName'] = "ice-checklist-for-test" + self.clbodydata['checkListTemplateUuid'] = str(self.template.uuid) + self.clbodydata[ + 'checkListAssociatedFiles'] = "[\"file0/f69f4ce7-51d5-409c-9d0e-ec6b1e79df28\", \"file1/f69f4ce7-51d5-409c-9d0e-ec6b1e79df28\", \"file2/f69f4ce7-51d5-409c-9d0e-ec6b1e79df28\"]" + + def loggerTestFailedOrSucceded(self, bool): + if bool: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test Succeeded") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + else: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug("Test failed") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + def testCreateAuditLogViaChecklistPositive(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: Create AuditLog Via Checklist") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/@cl_uuid/auditlog/" + + logger.debug("Creating a checklist") + self.auditdata['description'] = "description text" + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.post(self.urlStr.replace("@cl_uuid", str(self.checklist.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_200_OK)) + + check = True + try: + ChecklistAuditLog.objects.get(checklist=self.checklist) + except ChecklistAuditLog.DoesNotExist: + check = False + + if (response.status_code == HTTP_200_OK and check): + self.loggerTestFailedOrSucceded(True) + self.assertEqual(response.status_code, HTTP_200_OK) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_200_OK) + + def testCreateAuditLogViaChecklistNegativeEmptyDescription(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Negative Test started: Create AuditLog Via Checklist with empty description") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/@cl_uuid/auditlog/" + + logger.debug("Creating a checklist") + + self.auditdata['description'] = "" + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.post(self.urlStr.replace("@cl_uuid", str(self.checklist.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_400_BAD_REQUEST)) + + if (response.status_code == HTTP_400_BAD_REQUEST): + self.loggerTestFailedOrSucceded(True) + self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) + + def testCreateAuditLogViaChecklistNegativeBadCLUuid(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Negative Test started: Create AuditLog Via Checklist with bad CL uuid") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/@cl_uuid/auditlog/" + + logger.debug("Creating a checklist") + + self.auditdata['description'] = "description text" + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.post(self.urlStr.replace("@cl_uuid", str(uuid4())), + datajson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_500_INTERNAL_SERVER_ERROR)) + + if (response.status_code == HTTP_500_INTERNAL_SERVER_ERROR): + self.loggerTestFailedOrSucceded(True) + else: + self.loggerTestFailedOrSucceded(False) + + self.assertEqual(response.status_code, HTTP_500_INTERNAL_SERVER_ERROR) + + def testCreateAuditLogViaDecisionPositive(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: Create AuditLog Via Decision") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/decision/@decision_uuid/auditlog/" + + logger.debug("Creating a checklist") + + self.auditdata['description'] = "description text" + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.post(self.urlStr.replace("@decision_uuid", str(self.decision.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_200_OK)) + + check = ChecklistAuditLog.objects.get(decision=self.decision) + if (response.status_code == HTTP_200_OK and check): + self.loggerTestFailedOrSucceded(True) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_200_OK) + + def testCreateAuditLogViaDecisionNegativeEmptyDescription(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Negative Test started: Create AuditLog Via Decision with empty description") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/decision/@decision_uuid/auditlog/" + + logger.debug("Creating a checklist") + + self.auditdata['description'] = "" + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.post(self.urlStr.replace("@decision_uuid", str(self.decision.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_400_BAD_REQUEST)) + + if (response.status_code == HTTP_400_BAD_REQUEST): + self.loggerTestFailedOrSucceded(True) + self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) + + def testCreateAuditLogViaDecisionNegativeBadCLUuid(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Negative Test started: Create AuditLog Via Decision with bad Decision uuid") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/decision/@decision_uuid/auditlog/" + + logger.debug("Creating a checklist") + + self.auditdata['description'] = "description text" + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.post(self.urlStr.replace("@decision_uuid", str(uuid4())), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_400_BAD_REQUEST)) + + if (response.status_code == HTTP_400_BAD_REQUEST): + self.loggerTestFailedOrSucceded(True) + self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + def testSetDecisionPositive(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: Set decision's value to approved") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/decision/@decision_uuid" + + logger.debug("Creating a checklist") + + self.checklist.state = CheckListState.review.name # @UndefinedVariable + self.checklist.owner = self.el_user + self.checklist.save() + # @UndefinedVariable + self.auditdata['value'] = CheckListDecisionValue.approved.name + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.put(self.urlStr.replace("@decision_uuid", str(self.decision.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_200_OK)) + + check = ChecklistDecision.objects.get(checklist=self.checklist) + if (response.status_code == HTTP_200_OK and check.review_value == 'approved'): + self.loggerTestFailedOrSucceded(True) + self.assertEqual(response.status_code, HTTP_200_OK) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_200_OK) + + def testSetDecisionNegativeOwnerDifferentThanUser(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Negative Test started: Owner Different Than User") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/decision/@decision_uuid" + + logger.debug("Creating a checklist") + + self.checklist.state = CheckListState.review.name # @UndefinedVariable + self.checklist.owner = self.user + self.checklist.save() + # @UndefinedVariable + self.auditdata['value'] = CheckListDecisionValue.approved.name + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.put(self.urlStr.replace("@decision_uuid", str(self.decision.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_401_UNAUTHORIZED)) + + if (response.status_code == HTTP_401_UNAUTHORIZED): + self.loggerTestFailedOrSucceded(True) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + def testSetDecisionNegativeInvalidDecisionValue(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug("Negative Test started: Invalid Decision Value") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/decision/@decision_uuid" + + logger.debug("Creating a checklist") + + self.checklist.state = CheckListState.review.name # @UndefinedVariable + self.checklist.owner = self.el_user + self.checklist.save() + self.auditdata['value'] = self.randomGenerator("randomString") + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.put(self.urlStr.replace("@decision_uuid", str(self.decision.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_400_BAD_REQUEST)) + + if (response.status_code == HTTP_400_BAD_REQUEST): + self.loggerTestFailedOrSucceded(True) + self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) + + def testSetDecisionNegativeInvalidChecklistState(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug("Negative Test started: Invalid checklist state") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/decision/@decision_uuid" + + logger.debug("Creating a checklist") + + self.checklist.state = self.randomGenerator( + "randomString") # @UndefinedVariable + self.checklist.owner = self.el_user + self.checklist.save() + # @UndefinedVariable + self.auditdata['value'] = CheckListDecisionValue.approved.name + datajson = json.dumps(self.auditdata, ensure_ascii=False) + + response = self.c.put(self.urlStr.replace("@decision_uuid", str(self.decision.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Got response : ' + str(response.status_code) + + " Expecting " + str(HTTP_400_BAD_REQUEST)) + + if (response.status_code == HTTP_400_BAD_REQUEST): + self.loggerTestFailedOrSucceded(True) + self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, HTTP_405_METHOD_NOT_ALLOWED) diff --git a/django/engagementmanager/tests/test_auth_service.py b/django/engagementmanager/tests/test_auth_service.py new file mode 100755 index 0000000..b61de8d --- /dev/null +++ b/django/engagementmanager/tests/test_auth_service.py @@ -0,0 +1,244 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.models import Vendor +from engagementmanager.service.authorization_service import AuthorizationService, Permissions +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.utils.request_data_mgr import request_data_mgr + + +class TestAuthService(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + + self.createDefaultRoles() + + self.admin_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), Constants.service_provider_admin_mail, + '55501000199', 'admin user', self.admin, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.admin_user.uuid)) + print('Full Name: ' + self.admin_user.full_name) + print('-----------------------------------------------------') + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.el_user.uuid)) + print('Full Name: ' + self.el_user.full_name) + print('-----------------------------------------------------') + + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.peer_reviewer.uuid)) + print('Full Name: ' + self.peer_reviewer.full_name) + print('-----------------------------------------------------') + + # Create another EL + self.another_el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user2', self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.another_el_user.uuid)) + print('Full Name: ' + self.another_el_user.full_name) + print('-----------------------------------------------------') + + # Create a user with role standard_user + self.user = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user.uuid)) + print('Full Name: ' + self.user.full_name) + print('-----------------------------------------------------') + + # Create a user with role standard_user with SSH key + self.user_with_ssh = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'ssh user', self.standard_user, True, 'just-a-fake-ssh-key') + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user_with_ssh.uuid)) + print('Full Name: ' + self.user_with_ssh.full_name) + print('-----------------------------------------------------') + + # Create an Engagement with team + self.engagement = self.creator.createEngagement('just-a-fake-uuid', 'Validation', None) + self.engagement.engagement_team.add(self.user, self.el_user) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.save() + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement.uuid)) + print('-----------------------------------------------------') + + # Create another Engagement with team with SSH Key + self.engagement_ssh = self.creator.createEngagement('just-another-fake-uuid', 'Validation', None) + self.engagement_ssh.engagement_team.add(self.user_with_ssh, self.el_user) + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement_ssh.uuid)) + print('-----------------------------------------------------') + + # Create another Engagement with Main Contact + self.engagement_with_contact = self.creator.createEngagement('yet-just-another-fake-uuid', 'Validation', None) + self.engagement_with_contact.engagement_team.add(self.user_with_ssh, self.el_user) + self.engagement_with_contact.contact_user = self.user_with_ssh + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement_with_contact.uuid)) + print('-----------------------------------------------------') + + # Create another Engagement with Main Contact + self.engagement_4_createNS = self.creator.createEngagement('yet-just-another-fake-uuid2', 'Validation', None) + self.engagement_4_createNS.engagement_team.add(self.user_with_ssh, self.el_user) + self.engagement_4_createNS.contact_user = self.user_with_ssh + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement_4_createNS.uuid)) + print('-----------------------------------------------------') + self.token = self.loginAndCreateSessionToken(self.user) + self.sshtoken = self.loginAndCreateSessionToken(self.user_with_ssh) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + + self.checklist_template = self.creator.createDefaultCheckListTemplate() + print('-----------------------------------------------------') + print('Created Check List Template') + print('UUID: ' + str(self.checklist_template.uuid)) + print('-----------------------------------------------------') + + self.checklist = self.creator.createCheckList('some-checklist', 'Automation', 1, '{}', self.engagement, + self.checklist_template, self.el_user, self.peer_reviewer) + print('-----------------------------------------------------') + print('Created Check List') + print('UUID: ' + str(self.checklist.uuid)) + print('-----------------------------------------------------') + + def testAuthorization(self): + auth = AuthorizationService() + + ###################### + # TEST EL PERMISSIONS + ###################### + # Test Add VF for EL + auth_result, message = auth.is_user_able_to(self.el_user, Permissions.add_vf, str(self.engagement.uuid), '') + print('ADD_VF Got Result : ' + str(auth_result) + ' ' + message) + self.assertEquals(auth_result, True) + + auth_result, message = auth.is_user_able_to(self.el_user, Permissions.add_vendor, '', '') + print('ADD_VENDOR Got Result : ' + message) + self.assertEquals(auth_result, True) + + # Check that EL that belong to ENG can create next step + auth_result, message = auth.is_user_able_to( + self.el_user, Permissions.add_nextstep, str(self.engagement.uuid), '') + print('ADD_NEXTSTEP Got Result : ' + message) + self.assertEquals(auth_result, True) + + # Check that EL that does not belong to ENG cannot create next step + auth_result, message = auth.is_user_able_to( + self.another_el_user, Permissions.add_nextstep, str(self.engagement.uuid), '') + print('ADD_NEXTSTEP Got Result : ' + message) + self.assertEquals(auth_result, False) + + # Check that CL can be created only by EL that belongs to ENG + auth_result, message = auth.is_user_able_to( + self.el_user, Permissions.add_checklist, str(self.engagement.uuid), '') + print('ADD_CHECKLIST Got Result : ' + message) + self.assertEquals(auth_result, True) + + # Check that CL can be created only by EL that belongs to ENG (use another el) + auth_result, message = auth.is_user_able_to( + self.another_el_user, Permissions.add_checklist, str(self.engagement.uuid), '') + print('ADD_CHECKLIST Got Result : ' + message) + self.assertEquals(auth_result, False) + + auth_result, message = auth.is_user_able_to(self.user, Permissions.add_checklist, str(self.engagement.uuid), '') + print('ADD_CHECKLIST Got Result : ' + message) + self.assertEquals(auth_result, False) + + # Check that only peer reviewer can do peer review + request_data_mgr.set_cl_uuid(str(self.checklist.uuid)) + auth_result, message = auth.is_user_able_to( + self.peer_reviewer, Permissions.peer_review_checklist, str(self.engagement.uuid), str(self.checklist.uuid)) + print('PEER_REVIEW_CHECKLIST Got Result : ' + message) + self.assertEquals(auth_result, True) + + # Check that a user that is not defined as peer review cannot review + auth_result, message = auth.is_user_able_to( + self.el_user, Permissions.peer_review_checklist, str(self.engagement.uuid), str(self.checklist.uuid)) + print('PEER_REVIEW_CHECKLIST Got Result : ' + message) + self.assertEquals(auth_result, False) + + # Check that admin which is not owner cannot approve CL + # Test is greyed out due to the fact that admin can approve any CL +# auth_result, message = auth.is_user_able_to(self.admin_user, Permissions.admin_approve_checklist, str(self.engagement.uuid), str(self.checklist.uuid)) +# print('ADMIN_APPROVE_CHECKLIST Got Result : ' + message) +# self.assertEquals(auth_result, False) + + # Check that only admin which is the cl owner can approve CL + self.checklist.owner = self.admin_user # Make admin the owner + self.checklist.save() + auth_result, message = auth.is_user_able_to( + self.admin_user, Permissions.admin_approve_checklist, str(self.engagement.uuid), str(self.checklist.uuid)) + print('ADMIN_APPROVE_CHECKLIST Got Result : ' + message) + self.assertEquals(auth_result, True) + + # Check that only admin can approve CL (attempt with regular EL) + auth_result, message = auth.is_user_able_to( + self.el_user, Permissions.admin_approve_checklist, str(self.engagement.uuid), str(self.checklist.uuid)) + print('ADMIN_APPROVE_CHECKLIST Got Result : ' + message) + self.assertEquals(auth_result, False) + + # Check that only admin can approve CL (attempt with regular user) + auth_result, message = auth.is_user_able_to( + self.user, Permissions.admin_approve_checklist, str(self.engagement.uuid), str(self.checklist.uuid)) + print('ADMIN_APPROVE_CHECKLIST Got Result : ' + message) + self.assertEquals(auth_result, False) diff --git a/django/engagementmanager/tests/test_base_entity.py b/django/engagementmanager/tests/test_base_entity.py new file mode 100755 index 0000000..a90be1f --- /dev/null +++ b/django/engagementmanager/tests/test_base_entity.py @@ -0,0 +1,319 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from abc import ABCMeta, abstractmethod +import http.client +import inspect +import re +import django +from django.conf import settings +from django.test import TestCase +from django.test.client import Client +import psycopg2 +from rest_framework.parsers import JSONParser +from wheel.signatures import assertTrue +django.setup() +from engagementmanager.tests.vvpEntitiesCreator import VvpEntitiesCreator +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class TestBaseEntity(TestCase): + __metaclass__ = ABCMeta + + def setUp(self): + logger.debug("---------------------- TestCase " + self.__class__.__name__ + " ----------------------") + self.urlPrefix = "/ice/v1/engmgr/" + self.conn = http.client.HTTPConnection("127.0.0.1", 8000) # @UndefinedVariable + self.c = Client() + self.creator = VvpEntitiesCreator() + settings.IS_SIGNAL_ENABLED = False + self.childSetup() + + def tearDown(self): + settings.IS_SIGNAL_ENABLED = True + self.conn.close() + logger.debug("---------------------- TestCase " + self.__class__.__name__ + " ---------------------- ") + logger.debug("") + logger.debug("") + + def createVendors(self, vendorList): + for vendor in vendorList: + vendorUuid, vendor = self.creator.createVendor(vendor) + logger.debug(vendorUuid) + + def createDefaultRoles(self): + # Create Default Roles if does not exist + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + + def printTestName(self, testNameTrigger): + if testNameTrigger == "START": + logger.debug("[TestName: " + inspect.stack()[1][3] + " - START]") + elif testNameTrigger == "END": + logger.debug("[TestName: " + inspect.stack()[1][3] + " - END]") + + @abstractmethod + def childSetup(self): + pass + + def nativeConnect2Db(self): + return psycopg2.connect("dbname='icedb' user='iceuser' host='localhost' password='Aa123456' port='5433'") + + def deleteRecord(self, urlStr, getRecord, isNegativeTest): + logger.debug("DELETE: " + urlStr + "/" + getRecord) + self.conn.request("DELETE", urlStr + "/" + getRecord) + r1 = self.conn.getresponse() + logger.debug("DELETE response status code: " + str(r1.status)) +# logger.debug("Number of records in the table: " + self.getNumOfRecordViaRest(urlStr)) + if (isNegativeTest == False): + assertTrue(r1.status == 204) + return r1 + elif (isNegativeTest == True): + return r1 + + def createEntityViaPost(self, urlStr, params, headers=None): + logger.debug("POST: " + urlStr + " Body: " + params + " Headers: " + str(headers)) + self.conn.request("POST", urlStr, params, headers) + r1 = self.conn.getresponse() + return r1 + + def editEntityViaPut(self, urlStr, getRecord, params, isNegativeTest): + logger.debug("PUT: " + urlStr + "/" + getRecord + " " + params) + self.conn.request("PUT", urlStr + "/" + getRecord, params) + r1 = self.conn.getresponse() + logger.debug("PUT response status code: " + str(r1.status)) + if (isNegativeTest == False): + assertTrue(r1.status == 200) + return r1 + elif (isNegativeTest == True): + return r1 + + ''' + If you wish to "SELECT *" and get the first record then send queryFilterName=1 and queryFilterValue=1 to the method + ''' + + def filterTableByColAndVal(self, queryColumnName, queryTableName, queryFilterName, queryFilterValue): + dbConn = self.nativeConnect2Db() + cur = dbConn.cursor() + queryStr = "SELECT %s FROM %s WHERE %s ='%s'" % ( + queryColumnName, queryTableName, queryFilterName, queryFilterValue) + logger.debug(queryStr) + cur.execute(queryStr) + result = str(cur.fetchone()) + if (bool(re.search('[^0-9]', result)) == True): + logger.debug("Looks like result (" + result + + ") from DB is in a multi column pattern: [col1, col2,...,coln], omitting it all colm beside " + queryColumnName) + if (result.find("',)") != -1): # formatting strings e.g uuid + result = result.partition('\'')[-1].rpartition('\'')[0] + elif (result.find(",)") != -1): # formatting ints e.g id + result = result.partition('(')[-1].rpartition(',')[0] + logger.debug("Filter result: " + result) + return result + + def selectLastValue(self, queryColumnName, queryTableName, orderBy="id"): + dbConn = self.nativeConnect2Db() + cur = dbConn.cursor() + queryStr = "select %s from %s ORDER BY %s DESC LIMIT 1;" % (queryColumnName, queryTableName, orderBy) + logger.debug(queryStr) + cur.execute(queryStr) + result = str(cur.fetchone()) + if (bool(re.search('[^0-9]', result)) == True): + logger.debug("Looks like result (" + result + + ") from DB is in a multi column pattern: [col1, col2,...,coln], omitting it all colm beside " + queryColumnName) + if (result.find("',)") != -1): # formatting strings e.g uuid + result = result.partition('\'')[-1].rpartition('\'')[0] + elif (result.find(",)") != -1): # formatting ints e.g id + result = result.partition('(')[-1].rpartition(',')[0] + logger.debug("Filter result: " + result) + return result + + def columnMaxLength(self, tableName, columnName): + dbConn = self.nativeConnect2Db() + cur = dbConn.cursor() + queryStr = "SELECT character_maximum_length from information_schema.columns WHERE table_name ='%s' and column_name = '%s'" % ( + tableName, columnName) + cur.execute(queryStr) + result = str(cur.fetchone()) + if (bool(re.search('[^0-9]', result)) == True): + if (result.find("',)") != -1): # formatting strings e.g uuid + result = result.partition('\'')[-1].rpartition('\'')[0] + elif (result.find(",)") != -1): # formatting ints e.g id + result = result.partition('(')[-1].rpartition(',')[0] + return int(result) + + def getNumOfRecordViaRest(self, urlStr): + logger.debug("GET: " + urlStr) + self.conn.request("GET", urlStr) + data_list = JSONParser().parse(self.conn.getresponse()) + cnt = str(len(data_list)) + return cnt + + def getMaximalNameValue(self, urlStr): + logger.debug("GET: " + urlStr) + self.conn.request("GET", urlStr) + data_list = JSONParser().parse(self.conn.getresponse()) + maxName = 0 + for asi in data_list: + logger.debug(asi) + for key, value in asi.items(): + if (key == "name"): + if (maxName < int(value)): + maxName = int(value) + logger.debug("MaximalNameValue=" + str(maxName)) + return maxName + + def getRecordAndDeserilizeIt(self, urlStr, getFilter, serializer, isCreateObj): + logger.debug("GET: " + urlStr + "/" + getFilter) + try: + self.conn.request("GET", urlStr + "/" + getFilter) + data = JSONParser().parse(self.conn.getresponse()) + logger.debug("DATA After JSON Parse:" + str(data)) + ser = serializer(data=data) +# logger.debug(" --> Serializer data: "+repr(ser)) + if (isCreateObj == True): + logger.debug("Creating ...") + obj = ser.create(data) + else: + logger.debug("Updating ...") + obj = ser.create(data) + ser.update(obj, data) + except Exception: + logger.debug(Exception) + raise Exception + return obj + + def newParameters(self, oldValue, newValue, uuidValue): + newParams = re.sub(oldValue, newValue, self.params) # Find and replace in string. + newParams = re.sub("}", ', "uuid":"' + uuidValue + '"}', newParams) # Add UUID to params + return newParams + + def negativeTestPost(self, getFilter, allowTwice=False): + logger.debug("POST negative tests are starting now!") + if (allowTwice == False): + logger.debug("Negative 01: Insert the same record twice via REST") + r1 = self.createEntityViaPost(self.urlStr, self.params) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 400) + self.deleteRecord(self.urlStr, getFilter, False) + logger.debug("Negative 02: Insert record with empty value via REST") + paramsEmptyValue = re.sub(r':\".*?\"', ':\"\"', self.params) # Create params with empty values. + r1 = self.createEntityViaPost(self.urlStr, paramsEmptyValue) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 400) + logger.debug("Negative 03: Insert record with missing value via REST") + paramsMissingValue = re.sub(r'{\".*?\":', '{\"\":', self.params) # Create params without records part 1. + # Create params without records part 2. + paramsMissingValue = re.sub(r', \".*?\":', ', \"\":', paramsMissingValue) + r1 = self.createEntityViaPost(self.urlStr, paramsMissingValue) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 400) + logger.debug("Negative 04: Insert record with more than " + str(self.longValueLength) + " chars via REST") + paramsLongValue = re.sub( + r':\".*?\"', ':\"' + str(self.randomGenerator("randomNumber", self.longValueLength)) + '\"', self.params) + r1 = self.createEntityViaPost(self.urlStr, paramsLongValue) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 400) + if (allowTwice == True): + logger.debug("Deleting record from database...") + self.deleteRecord(self.urlStr, getFilter, False) + + def negativeTestPut(self, getFilter, params): + logger.debug("PUT negative tests are starting now!") + match = re.search("\D", getFilter) # Check if getFilter contains non-digit characters. + if not match: + logger.debug("Negative 01: Edit non existing record via REST") + nonExistingValue = self.randomGenerator("randomNumber", 5) + r1 = self.editEntityViaPut(self.urlStr, nonExistingValue, params, True) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 404) + logger.debug("Negative 02: Edit record with string in URL instead of integer via REST") + randStr = self.randomGenerator("randomString") + r1 = self.editEntityViaPut(self.urlStr, randStr, params, True) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 400) + else: + logger.debug("Negative 01: Edit non existing record via REST") + nonExistingValue = self.randomGenerator("randomString") + r1 = self.editEntityViaPut(self.urlStr, nonExistingValue, params, True) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 404) + logger.debug("Negative 02: Edit record without URL pointer via REST") + r1 = self.editEntityViaPut(self.urlStr, "", params, True) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 405) + logger.debug("Negative 03: Edit record with empty value via REST") + paramsEmptyValue = re.sub(r':\".*?\"', ':\"\"', params) # Create params with empty values. + r1 = self.editEntityViaPut(self.urlStr, getFilter, paramsEmptyValue, True) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 400) + logger.debug("Negative 04: Edit record with missing value via REST") + paramsMissingValue = re.sub(r'{\".*?\":', '{\"\":', params) # Create params without records part 1. + # Create params without records part 2. + paramsMissingValue = re.sub(r', \".*?\":', ', \"\":', paramsMissingValue) + r1 = self.editEntityViaPut(self.urlStr, getFilter, paramsMissingValue, True) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 400) + logger.debug("Deleting record from database...") + self.deleteRecord(self.urlStr, getFilter, False) + + def negativeTestDelete(self): + logger.debug("DELETE negative tests are starting now!") + logger.debug("Negative 01: Delete non existing record via REST or wrong URL pointer") + nonExistingValue = self.randomGenerator("randomString") + r1 = self.deleteRecord(self.urlStr, nonExistingValue, True) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 404 or r1.status == 500 or r1.status == 400) + logger.debug("Negative 02: Delete record without URL pointer via REST") + r1 = self.deleteRecord(self.urlStr, "", True) + logger.debug(r1.status, r1.reason) + assertTrue(r1.status == 405) + + def failTest(self, failureReason): + logger.debug(">>> Test failed!\n", failureReason) + self.assertTrue(False) + + def failRestTest(self, r1): + logger.debug("Previous HTTP POST request has failed with " + str(r1.status)) + self.assertTrue(False) + + def randomGenerator(self, typeOfValue, numberOfDigits=0): + return self.creator.randomGenerator(typeOfValue, numberOfDigits) + + def loginAndCreateSessionToken(self, user): + return self.creator.loginAndCreateSessionToken(user) diff --git a/django/engagementmanager/tests/test_base_transaction_entity.py b/django/engagementmanager/tests/test_base_transaction_entity.py new file mode 100755 index 0000000..c4a5159 --- /dev/null +++ b/django/engagementmanager/tests/test_base_transaction_entity.py @@ -0,0 +1,76 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from abc import ABCMeta, abstractmethod +import http.client +import django +from django.conf import settings +from django.test.client import Client +from django.test.testcases import TransactionTestCase +from engagementmanager.tests.vvpEntitiesCreator import VvpEntitiesCreator +from engagementmanager.service.logging_service import LoggingServiceFactory +django.setup() +logger = LoggingServiceFactory.get_logger() + + +class TestBaseTransactionEntity(TransactionTestCase): + __metaclass__ = ABCMeta + + def setUp(self): + logger.debug("---------------------- TransactionTestCase " + self.__class__.__name__ + " ----------------------") + self.urlPrefix = "/ice/v1/engmgr/" + self.conn = http.client.HTTPConnection("127.0.0.1", 8000) # @UndefinedVariable + self.c = Client() + self.creator = VvpEntitiesCreator() + settings.IS_SIGNAL_ENABLED = False + self.childSetup() + + def tearDown(self): + settings.IS_SIGNAL_ENABLED = True + self.conn.close() + logger.debug("---------------------- TransactionTestCase " + self.__class__.__name__ + " ---------------------- ") + + @abstractmethod + def childSetup(self): + pass + + def randomGenerator(self, typeOfValue, numberOfDigits=0): + return self.creator.randomGenerator(typeOfValue, numberOfDigits) + + def loginAndCreateSessionToken(self, user): + return self.creator.loginAndCreateSessionToken(user) diff --git a/django/engagementmanager/tests/test_checklist.py b/django/engagementmanager/tests/test_checklist.py new file mode 100755 index 0000000..a7fa800 --- /dev/null +++ b/django/engagementmanager/tests/test_checklist.py @@ -0,0 +1,177 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from uuid import uuid4 + +from rest_framework.status import HTTP_200_OK, HTTP_401_UNAUTHORIZED, HTTP_400_BAD_REQUEST + +from engagementmanager.models import ChecklistTemplate, ChecklistLineItem +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants + + +class TestChecklistTestCase(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs', 'Other']) + self.createDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + # For negative tests + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + self.urlStr = self.urlPrefix + "engagement/@eng_uuid/checklist/new/" + self.data = dict() + self.template = self.creator.createDefaultCheckListTemplate() +# self.engagement = Engagement.objects.create(uuid='just-a-fake-uuid',engagement_stage='Validation') + self.engagement = self.creator.createEngagement( + uuid4(), 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.engagement_team.add(self.user) + self.engagement.engagement_team.add(self.el_user) + self.engagement.save() + self.vendor = Vendor.objects.get(name='Other') + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, self.vendor) + + def initBody(self): + self.data['checkListName'] = "ice checklist for test" + self.data['checkListTemplateUuid'] = str(self.template.uuid) + self.data['checkListAssociatedFiles'] = list() + self.data['checkListAssociatedFiles'].append("file0") + self.data['checkListAssociatedFiles'].append("file1") + self.data['checkListAssociatedFiles'].append("file2") + + def getOrCreateChecklist(self, expectedStatus=HTTP_200_OK, httpMethod="GET"): + if (httpMethod == "GET"): + response = self.c.get(self.urlStr.replace("@eng_uuid", str(self.engagement.uuid)), + **{'HTTP_AUTHORIZATION': "token " + self.token}) + elif (httpMethod == "POST"): + datajson = json.dumps(self.data, ensure_ascii=False) + response = self.c.post(self.urlStr.replace("@eng_uuid", str(self.engagement.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + + print('Got response : ' + str(response.status_code) + + " Expecting " + str(expectedStatus)) + self.assertEqual(response.status_code, expectedStatus) + return response + + def testGetChecklistPositive(self): + self.token = self.loginAndCreateSessionToken(self.el_user) + print("testGetChecklistPositive") + self.getOrCreateChecklist(HTTP_200_OK) + + def testGetChecklistNegativeNoEng(self): + self.token = self.loginAndCreateSessionToken(self.el_user) + self.engagement.uuid = uuid4() + print("testGetChecklistPositive") + self.getOrCreateChecklist(HTTP_401_UNAUTHORIZED) +# + + def testPostChecklistPositive(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.el_user) + print("testPostChecklistPositive") + self.getOrCreateChecklist(HTTP_200_OK, "POST") + + def testPostChecklistNegativeNotElUser(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.user) + print("testPostChecklistNegativeNotElUser") + self.getOrCreateChecklist(HTTP_401_UNAUTHORIZED, "POST") + + def testPostChecklistNegativeNoEng(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.el_user) + self.engagement.uuid = uuid4() + print("testPostChecklistNegativeNoEng") + self.getOrCreateChecklist(HTTP_401_UNAUTHORIZED, "POST") + + def testPostChecklistNegativeMissingParam(self): + self.token = self.loginAndCreateSessionToken(self.el_user) + print("testPostChecklistNegativeMissingParam") + self.getOrCreateChecklist(HTTP_400_BAD_REQUEST, "POST") + + def testPostTestEngineDecisions(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.el_user) + print("testGetChecklistPositive") + response = self.getOrCreateChecklist(HTTP_200_OK, "POST") + + checklist = json.loads(response.content) + self.urlStr = self.urlPrefix + "checklist/@checklist_uuid/testengine/" + + # ChecklistLineItem.objects.get(uuid=decision['line_item_id']); + + print(checklist['template']['uuid']) + template = ChecklistTemplate.objects.get( + uuid=checklist['template']['uuid']) + print(template) + line_items = ChecklistLineItem.objects.filter(template=template) + for line_item in line_items: + print(line_item) + + return + self.data = dict() + self.data['decisions'] = "{123}" + datajson = json.dumps(self.data, ensure_ascii=False) + response = self.c.get(self.urlStr.replace("@checklist_uuid", str(checklist['uuid'])), + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + + print(json.loads(response.content)) + + return + + self.data = dict() + self.data['decisions'] = "{123}" + datajson = json.dumps(self.data, ensure_ascii=False) + response = self.c.post(self.urlStr.replace("@checklist_uuid", str(checklist['uuid'])), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) diff --git a/django/engagementmanager/tests/test_checklist_template.py b/django/engagementmanager/tests/test_checklist_template.py new file mode 100755 index 0000000..c3c63e4 --- /dev/null +++ b/django/engagementmanager/tests/test_checklist_template.py @@ -0,0 +1,168 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +import mock +from rest_framework.status import HTTP_200_OK, HTTP_404_NOT_FOUND,\ + HTTP_500_INTERNAL_SERVER_ERROR + +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants + + +def dummy_true(): + return True + + +@mock.patch('engagementmanager.service.checklist_service.CheckListSvc.decline_all_template_checklists', dummy_true) +class TestChecklistTestCase(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs', 'Other']) + self.createDefaultRoles() + # Create a user with role el + self.el_user = self.creator.createUser( + Vendor.objects.get(name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.admin_user = self.creator.createUser(Vendor.objects.get(name=Constants.service_provider_company_name), + Constants.service_provider_admin_mail, '55501000199', + 'admin user', self.admin, True) + # For negative tests + self.user = self.creator.createUser( + Vendor.objects.get(name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + self.urlStrForSave = self.urlPrefix + "checklist/template/" + self.urlStrForGetTmpl = self.urlPrefix + "checklist/template/@template_uuid" + self.urlStrForGetTmpls = self.urlPrefix + "checklist/templates/" + self.data = dict() + self.template = self.creator.createDefaultCheckListTemplate() + self.engagement = self.creator.createEngagement('just-a-fake-uuid', 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.el_user + self.engagement.engagement_team.add(self.user) + self.engagement.engagement_team.add(self.el_user) + self.engagement.save() + self.vendor = Vendor.objects.get(name='Other') + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF( + self.randomGenerator("randomString"), self.engagement, self.deploymentTarget, False, self.vendor) + + def initBody(self): + self.data['uuid'] = str(self.template.uuid) + self.data['name'] = self.template.name + self.data['sections'] = list() + li1 = dict() + li1["uuid"] = "newEntity" + li1["name"] = "li1_name" + li1["description"] = "li1_description" + li1["validation_instructions"] = "li1_validation_instructions" + + sec1 = dict() + sec1["uuid"] = "newEntity" + sec1["name"] = "sec1_name" + sec1["description"] = "sec1_description" + sec1["validation_instructions"] = "sec1_validation_instructions" + + sec1["lineItems"] = list() + sec1["lineItems"].append(li1) + + self.data['sections'].append(sec1) + print(self.data) + + def getOrCreateChecklistTemplate(self, urlStr, expectedStatus=HTTP_200_OK, httpMethod="GET"): + if (httpMethod == "GET"): + if (urlStr == self.urlStrForGetTmpls): + response = self.c.get(urlStr, + **{'HTTP_AUTHORIZATION': "token " + self.token}) + else: + response = self.c.get(urlStr.replace("@template_uuid", str(self.template.uuid)), + **{'HTTP_AUTHORIZATION': "token " + self.token}) + elif (httpMethod == "PUT"): + datajson = json.dumps(self.data, ensure_ascii=False) + response = self.c.put( + urlStr, datajson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code) + " Expecting " + str(expectedStatus)) + print('Got response : ' + str(response.status_code) + " Expecting " + str(expectedStatus)) + self.assertEqual(response.status_code, expectedStatus) + return response + + ### TESTS ### + def testSaveChecklistTemplate(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.admin_user) + print("testSaveChecklistTemplate") + self.getOrCreateChecklistTemplate(self.urlStrForSave, httpMethod="PUT") + + def testSaveChecklistTemplateMissingTemplateUuid(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.admin_user) + self.data['uuid'] = "" + print("testSaveChecklistTemplateMissingTemplateUuid") + self.getOrCreateChecklistTemplate(self.urlStrForSave, expectedStatus=HTTP_404_NOT_FOUND, httpMethod="PUT") + + def testSaveChecklistTemplateNotExistingTemplate(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.admin_user) + print("testSaveChecklistTemplateNoExistanceTemplate") + self.data['uuid'] = 'fake_uuid' + self.getOrCreateChecklistTemplate(self.urlStrForSave, expectedStatus=HTTP_404_NOT_FOUND, httpMethod="PUT") + + def testSaveChecklistTemplateMissingKey(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.admin_user) + print("testSaveChecklistTemplateNoExistanceTemplate") + # take the first line item (li1_name) which is newEntity and remove its name, expect 500 + self.data['sections'][0]["lineItems"][0]["name"] = None + self.getOrCreateChecklistTemplate( + self.urlStrForSave, expectedStatus=HTTP_500_INTERNAL_SERVER_ERROR, httpMethod="PUT") + + def testGetChecklistTemplates(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.admin_user) + print("testSaveChecklistTemplate") + self.getOrCreateChecklistTemplate(self.urlStrForGetTmpls, httpMethod="GET") + + def testGetChecklistTemplate(self): + self.initBody() + self.token = self.loginAndCreateSessionToken(self.admin_user) + print("testSaveChecklistTemplate") + self.getOrCreateChecklistTemplate(self.urlStrForGetTmpl, httpMethod="GET") diff --git a/django/engagementmanager/tests/test_cms_documentation_search.py b/django/engagementmanager/tests/test_cms_documentation_search.py new file mode 100755 index 0000000..2d13f96 --- /dev/null +++ b/django/engagementmanager/tests/test_cms_documentation_search.py @@ -0,0 +1,103 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import mock +from rest_framework.status import HTTP_200_OK +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def search_page_mock(keyword): + result = [{u'id': 1, u'title': 'exists_title', u'children': [], u'status': '', u'_order': 1}, ] + return result + + +def search_empty_page_mock(keyword): + return [] + + +class TestCMSDocumentationSearch(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + self.user = self.creator.createUser(Vendor.objects.get(name='Other'), + self.randomGenerator("main-vendor-email"), 'Aa123456', + 'user', self.standard_user, True) + self.token = self.loginAndCreateSessionToken(self.user) + + def testSearchEmptyString(self): + urlStr = self.urlPrefix + 'cms/pages/search/?keyword=' + self.printTestName("testSearchEmptyString [Start]") + logger.debug("action should success (200), and return empty array") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + content = json.loads(response.content) + self.assertEqual(content, []) + self.printTestName("testSearchEmptyString [End]") + + @mock.patch('engagementmanager.apps.cms_client.search_pages', search_empty_page_mock) + def testSearchNotExistsKeyword(self): + urlStr = self.urlPrefix + 'cms/pages/search/?keyword=somewordnotexists' + self.printTestName("testSearchNotExistsKeyword [Start]") + logger.debug("action should success (200), and return empty array") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + content = json.loads(response.content) + self.assertEqual(content, []) + self.printTestName("testSearchNotExistsKeyword [End]") + + @mock.patch('engagementmanager.apps.cms_client.search_pages', search_page_mock) + def testSearchExistsKeyword(self): + urlStr = self.urlPrefix + 'cms/pages/search/?keyword=exists_title' + self.printTestName("testSearchExistsKeyword [Start]") + logger.debug("action should success (200), and return array with one page (by mock)") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + content = json.loads(response.content) + self.assertEqual(content[0]['title'], 'exists_title') + self.printTestName("testSearchExistsKeyword [End]") diff --git a/django/engagementmanager/tests/test_cms_pages.py b/django/engagementmanager/tests/test_cms_pages.py new file mode 100755 index 0000000..4fd9473 --- /dev/null +++ b/django/engagementmanager/tests/test_cms_pages.py @@ -0,0 +1,135 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import mock +from rest_framework.status import HTTP_200_OK +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def get_pages_mock(title=""): + result = [{u'meta_description': u'Content of page #1', u'parent': None, u'title': u'Page #1', + u'login_required': True, u'children': [], u'id': 1, + u'content': u'<p>Content of page #1</p>', u'content_model': u'richtextpage', + u'publish_date': u'2017-01-01T13:47:15Z', u'slug': u'documentation/page#1', u'tags': u''}, + {u'meta_description': u'Content of page #2', u'parent': None, u'title': u'Page #2', + u'login_required': True, u'children': [], u'id': 2, + u'content': u'<p>Content of page #2</p>', u'content_model': u'richtextpage', + u'publish_date': u'2017-01-01T13:47:15Z', u'slug': u'documentation/page#2', u'tags': u''}, + {u'meta_description': u'Content of page #3', u'parent': None, u'title': u'Page #3', + u'login_required': True, u'children': [], u'id': 3, + u'content': u'<p>Content of page #3</p>', u'content_model': u'richtextpage', + u'publish_date': u'2017-01-01T13:47:15Z', u'slug': u'documentation/page#3', u'tags': u''}, + {u'meta_description': u'Content of page #4', u'parent': None, u'title': u'Page #4', + u'login_required': True, u'children': [], u'id': 4, + u'content': u'<p>Content of page #4</p>', u'content_model': u'richtextpage', + u'publish_date': u'2017-01-01T13:47:15Z', u'slug': u'documentation/page#4', u'tags': u''}, + {u'meta_description': u'Content of page #5', u'parent': None, u'title': u'Page #5', + u'login_required': True, u'children': [], u'id': 5, + u'content': u'<p>Content of page #5</p>', u'content_model': u'richtextpage', + u'publish_date': u'2017-01-01T13:47:15Z', u'slug': u'documentation/page#5', u'tags': u''}, + {u'meta_description': u'Content of page #6', u'parent': None, u'title': u'Page #6', + u'login_required': True, u'children': [], u'id': 6, + u'content': u'<p>Content of page #6</p>', u'content_model': u'richtextpage', + u'publish_date': u'2017-01-01T13:47:15Z', u'slug': u'documentation/page#6', u'tags': u''}] + if title != "": + return [result[0]] + else: + return result + + +def get_page_mock(id): + result = {u'meta_description': u'Content of page #1', u'parent': None, u'title': u'Page #1', + u'login_required': True, u'children': [], u'id': 1, + u'content': u'<p>Content of page #1</p>', u'content_model': u'richtextpage', + u'publish_date': u'2017-01-01T13:47:15Z', u'slug': u'documentation/page#1', u'tags': u''} + + return result + + +@mock.patch('engagementmanager.apps.cms_client.get_pages', get_pages_mock) +@mock.patch('engagementmanager.apps.cms_client.get_page', get_page_mock) +class CMSGetPagesTestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + self.user = self.creator.createUser(Vendor.objects.get(name='Other'), + self.randomGenerator("main-vendor-email"), 'Aa123456', + 'user', self.standard_user, True) + self.token = self.loginAndCreateSessionToken(self.user) + + def testGetPageById(self): + urlStr = self.urlPrefix + 'cms/pages/1/' + self.printTestName("testGetPageById [Start]") + logger.debug("action should success (200), and return page by id") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + content = json.loads(response.content) + self.assertEqual(content["title"], 'Page #1') + self.printTestName("testGetPageById [End]") + + def testGetPages(self): + urlStr = self.urlPrefix + 'cms/pages/' + self.printTestName("testGetPages [Start]") + logger.debug("action should success (200), and return all pages") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(len(json.loads(response.content)), 6) # Suppose to be 6 The amount of Pages in the mock. + self.printTestName("testGetPages [End]") + + def testGetPagesByTitle(self): + urlStr = self.urlPrefix + 'cms/pages/?title=Documentation' + print(urlStr) + self.printTestName("testGetPagesByTitle [Start]") + logger.debug("action should success (200), and return filtered pages") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + content = json.loads(response.content) + self.assertEqual(len(content), 1) # Suppose to be 1 The amount of Documentation titled pages in the mock. + self.assertEqual(content[0]["title"], 'Page #1') + self.printTestName("testGetPagesByTitle [End]") diff --git a/django/engagementmanager/tests/test_cms_posts.py b/django/engagementmanager/tests/test_cms_posts.py new file mode 100755 index 0000000..7132c2c --- /dev/null +++ b/django/engagementmanager/tests/test_cms_posts.py @@ -0,0 +1,137 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import mock +from rest_framework.status import HTTP_200_OK +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def get_posts_mock(offset=0, limit=10, category="", date_min=""): + result = [{u'updated': u'2017-01-17T15:57:19.567778Z', u'title': u'announcement..new.1', u'url': u'http://127.0.0.1:8001/blog/announcementnew1/', u'short_url': u'/blog/announcementnew1/', u'tags': u'', u'excerpt': u'announcement..new.announcement..new.', u'allow_comments': True, u'comments': [], u'slug': u'announcementnew1', u'content': u'<p>announcement..new.announcement..new.</p>', u'publish_date': u'2017-01-14T19:53:52Z', u'user': {u'username': u'al942u', u'first_name': u'', u'last_name': u'', u'email': u'al942u@mail.com', u'is_staff': True, u'id': 1}, u'featured_image': u'', u'comments_count': 0, u'id': 1, u'categories': [{u'slug': u'announcement', u'id': 1, u'title': u'Announcement'}]}, + {u'updated': u'2017-01-16T15:57:19.567778Z', u'title': u'announcement..new.2', u'url': u'http://127.0.0.1:8001/blog/announcementnew2/', u'short_url': u'/blog/announcementnew2/', u'tags': u'', u'excerpt': u'announcement..new.announcement..new.', u'allow_comments': True, u'comments': [], u'slug': u'announcementnew2', + u'content': u'<p>announcement..new.announcement..new.</p>', u'publish_date': u'2017-01-15T19:53:52Z', u'user': {u'username': u'al942u', u'first_name': u'', u'last_name': u'', u'email': u'al942u@mail.com', u'is_staff': True, u'id': 1}, u'featured_image': u'', u'comments_count': 0, u'id': 2, u'categories': [{u'slug': u'announcement', u'id': 1, u'title': u'Announcement'}]}, + {u'updated': u'2017-01-15T15:57:19.567778Z', u'title': u'announcement..new.3', u'url': u'http://127.0.0.1:8001/blog/announcementnew3/', u'short_url': u'/blog/announcementnew3/', u'tags': u'', u'excerpt': u'announcement..new.announcement..new.', u'allow_comments': True, u'comments': [], u'slug': u'announcementnew3', + u'content': u'<p>announcement..new.announcement..new.</p>', u'publish_date': u'2017-01-16T19:53:52Z', u'user': {u'username': u'al942u', u'first_name': u'', u'last_name': u'', u'email': u'al942u@mail.com', u'is_staff': True, u'id': 1}, u'featured_image': u'', u'comments_count': 0, u'id': 3, u'categories': [{u'slug': u'announcement', u'id': 1, u'title': u'Announcement'}]}, + {u'updated': u'2017-01-14T15:57:19.567778Z', u'title': u'news..new.1', u'url': u'http://127.0.0.1:8001/blog/news1/', u'short_url': u'/blog/news1/', u'tags': u'', u'excerpt': u'news..new.news..new.', u'allow_comments': True, u'comments': [], u'slug': u'news1', u'content': u'<p>news..new.news..new.</p>', + u'publish_date': u'2017-01-14T19:53:52Z', u'user': {u'username': u'al942u', u'first_name': u'', u'last_name': u'', u'email': u'al942u@mail.com', u'is_staff': True, u'id': 1}, u'featured_image': u'', u'comments_count': 0, u'id': 4, u'categories': [{u'slug': u'news', u'id': 1, u'title': u'News'}]}, + {u'updated': u'2017-01-13T15:57:19.567778Z', u'title': u'news..new.2', u'url': u'http://127.0.0.1:8001/blog/news2/', u'short_url': u'/blog/news2/', u'tags': u'', u'excerpt': u'news..new.news..new.', u'allow_comments': True, u'comments': [], u'slug': u'news2', u'content': u'<p>news..new.news..new.</p>', + u'publish_date': u'2017-01-15T19:53:52Z', u'user': {u'username': u'al942u', u'first_name': u'', u'last_name': u'', u'email': u'al942u@mail.com', u'is_staff': True, u'id': 1}, u'featured_image': u'', u'comments_count': 0, u'id': 5, u'categories': [{u'slug': u'news', u'id': 1, u'title': u'News'}]}, + {u'updated': u'2017-01-12T15:57:19.567778Z', u'title': u'news..new.3', u'url': u'http://127.0.0.1:8001/blog/news3/', u'short_url': u'/blog/news3/', u'tags': u'', u'excerpt': u'news..new.news..new.', u'allow_comments': True, u'comments': [], u'slug': u'news3', u'content': u'<p>news..new.news..new.</p>', u'publish_date': u'2017-01-16T19:53:52Z', u'user': {u'username': u'al942u', u'first_name': u'', u'last_name': u'', u'email': u'al942u@mail.com', u'is_staff': True, u'id': 1}, u'featured_image': u'', u'comments_count': 0, u'id': 6, u'categories': [{u'slug': u'news', u'id': 1, u'title': u'News'}]}] + + if category == "News": + return [result[3], result[4], result[5]] + elif date_min != "": + return [result[0], result[1]] + elif category == "Announcement" and limit == 1: + return [result[0]] + elif limit != 10: + return result[:int(limit)] + else: + return result + + +@mock.patch('engagementmanager.apps.cms_client.get_posts', get_posts_mock) +class CMSGetPostsTestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + self.user = self.creator.createUser(Vendor.objects.get(name='Other'), + self.randomGenerator("main-vendor-email"), 'Aa123456', + 'user', self.standard_user, True) + self.token = self.loginAndCreateSessionToken(self.user) + + def testGetPostsByCategory(self): + urlStr = self.urlPrefix + 'cms/posts/?category=News' + print(urlStr) + self.printTestName("GetPostsByCategoryTest [Start]") + logger.debug("action should success (200), and return filtered posts") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(len(json.loads(response.content)), 3) # Suppose to be 3 The amount of News in the mock. + self.printTestName("GetPostsByCategoryTest [End]") + + def testGetAllPosts(self): + urlStr = self.urlPrefix + 'cms/posts/?limit=10' + self.printTestName("GetAllPostsTest [Start]") + logger.debug("action should success (200), and return all posts") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + # Suppose to be 6 items like the amount of items of the mock. + self.assertEqual(len(json.loads(response.content)), 6) + self.printTestName("GetAllPostsTest [End]") + + def testGetLimitedPosts(self): + limit = 2 + urlStr = self.urlPrefix + 'cms/posts/?limit=' + str(limit) + self.printTestName("GetLimitedPostsTest [Start]") + logger.debug("action should success (200), and filtered with limit all posts") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(len(json.loads(response.content)), limit) # Suppose to be {{limit}} amount of items + self.printTestName("GetLimitedPostsTest [End]") + + def testGetPostsByDateMin(self): + urlStr = self.urlPrefix + 'cms/posts/?fromLastDays=2&limit=10' + self.printTestName("GetPostsByDateMinTest [Start]") + logger.debug("action should success (200), and return filtered posts") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(len(json.loads(response.content)), 2) # Suppose to be 2 items that are after this date + self.printTestName("GetPostsByDateMinTest [End]") + + def testGetOneAnnouncementPost(self): + urlStr = self.urlPrefix + 'cms/posts/?limit=1&category=Announcement' + self.printTestName("GetOneAnnouncementPostTest [Start]") + logger.debug("action should success (200), and return one announcement post") + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(len(json.loads(response.content)), 1) # Suppose to be just 1 item like that. + self.printTestName("GetOneAnnouncementPostTest [End]") diff --git a/django/engagementmanager/tests/test_deployment_target_sites.py b/django/engagementmanager/tests/test_deployment_target_sites.py new file mode 100755 index 0000000..ddfb448 --- /dev/null +++ b/django/engagementmanager/tests/test_deployment_target_sites.py @@ -0,0 +1,163 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.status import HTTP_200_OK, HTTP_401_UNAUTHORIZED +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class DeploymentTargetSitesTestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + + # Create users: + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + self.el_user = self.creator.createUser(Vendor.objects.get(name=Constants.service_provider_company_name), + self.randomGenerator("main-vendor-email"), 'Aa123456', + 'el user1', self.el, True) + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), 'Aa123456', + 'user', self.standard_user, True) + self.admin_user = self.creator.createUser(Vendor.objects.get(name=Constants.service_provider_company_name), + Constants.service_provider_admin_mail, 'Aa123456', + 'admin user', self.admin, True) + + # Create an Engagement with team + self.engagement = self.creator.createEngagement( + 'just-a-fake-uuid', 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.engagement_team.add(self.user, self.el_user) + self.engagement.save() + self.deploymentTarget = self.creator.createDeploymentTarget(self.randomGenerator("randomString"), + self.randomGenerator("randomString")) + self.vendor = Vendor.objects.get(name=Constants.service_provider_company_name) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), self.engagement, + self.deploymentTarget, False, self.vendor) + + # Login with users: + self.user_token = self.loginAndCreateSessionToken(self.user) + self.el_token = self.loginAndCreateSessionToken(self.el_user) + self.admin_token = self.loginAndCreateSessionToken(self.admin_user) + + def testPostDeploymentTargetSitesForStandardUser(self): + urlStr = self.urlPrefix + 'dtsites/' + + myjson = '{"name": "Middletown (ICENJ)", "vf_uuid": "' + \ + str(self.vf.uuid) + '"}' + print(myjson) + + response = self.c.post(urlStr, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.user_token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + def testPostDeploymentTargetSitesForELUser(self): + urlStr = self.urlPrefix + 'dtsites/' + + myjson = '{"name": "Middletown (ICENJ)", "vf_uuid": "' + \ + str(self.vf.uuid) + '"}' + print(myjson) + + response = self.c.post(urlStr, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.el_token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + def testPostDeploymentTargetSitesForAdminUser(self): + urlStr = self.urlPrefix + 'dtsites/' + + myjson = '{"name": "Middletown (ICENJ)", "vf_uuid": "' + \ + str(self.vf.uuid) + '"}' + print(myjson) + + response = self.c.post(urlStr, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + def testGetDeploymentTargetSitesForStandardUser(self): + urlStr = self.urlPrefix + 'vf/' + str(self.vf.uuid) + '/dtsites/' + print(urlStr) + self.printTestName("testGetDeploymentTargetSites [Start]") + logger.debug("action should unauthorized (401)") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.user_token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + self.printTestName("testGetDeploymentTargetSites [End]") + + def testGetDeploymentTargetSitesForELUser(self): + urlStr = self.urlPrefix + 'vf/' + str(self.vf.uuid) + '/dtsites/' + print(urlStr) + self.printTestName("testGetDeploymentTargetSitesForELUser [Start]") + logger.debug("action should authorized (200)") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.el_token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.printTestName("testGetDeploymentTargetSitesForELUser [End]") + + def testGetDeploymentTargetSitesForAdminUser(self): + urlStr = self.urlPrefix + 'vf/' + str(self.vf.uuid) + '/dtsites/' + print(urlStr) + self.printTestName("testGetDeploymentTargetSitesForAdminUser [Start]") + logger.debug("action should authorized (200)") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.printTestName("testGetDeploymentTargetSitesForAdminUser [End]") + + def testDelDeploymentTargetSitesForStandardUser(self): + urlStr = self.urlPrefix + 'vf/' + str(self.vf.uuid) + '/dtsites/' + print(urlStr) + logger.debug("action should unauthorized (401)") + response = self.c.delete( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.user_token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) diff --git a/django/engagementmanager/tests/test_digest_email_notifications.py b/django/engagementmanager/tests/test_digest_email_notifications.py new file mode 100755 index 0000000..b3e75df --- /dev/null +++ b/django/engagementmanager/tests/test_digest_email_notifications.py @@ -0,0 +1,128 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import mock +from rest_framework.status import HTTP_202_ACCEPTED +from engagementmanager.bus.messages.activity_event_message import ActivityEventMessage +from engagementmanager.bus.messages.daily_scheduled_message import DailyScheduledMessage +from engagementmanager.models import Vendor +from engagementmanager.utils.activities_data import UserJoinedEngagementActivityData +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants, EngagementStage +from engagementmanager.apps import bus_service +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def digest_mock(self, bus_message): + DigestEmailNotificationsTestCase.is_digested_mock_sent = True + DigestEmailNotificationsTestCase.message = bus_message + + +# engagementmanager/bus/handlers/digest_email_notification_handler.py +@mock.patch('engagementmanager.bus.handlers.digest_email_notification_handler.' + 'DigestEmailNotificationHandler.handle_message', digest_mock) +class DigestEmailNotificationsTestCase(TestBaseEntity): + is_digested_mock_sent = False + message = None + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + + self.createDefaultRoles() + vendor = Vendor.objects.get(name=Constants.service_provider_company_name) + self.el_user = self.creator.createUser(vendor, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + vendor = Vendor.objects.get(name='Other') + self.user = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + self.pruser = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + + self.engagement = self.creator.createEngagement(self.randomGenerator( + "randomString"), self.randomGenerator("randomString"), None) + self.engagement.engagement_team.add(self.user, self.el_user) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.pruser + self.engagement.save() + + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, vendor) + + def testDigestEmailForActivities(self): + """ + Will check if the service bus deliver the message of sending digested mails + No need to check if the mail is sent or if the python scheduling is working + """ + # Create the activities: + self.urlStr = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + "/stage/@stage" + + random_user = self.creator.createUser(Vendor.objects.get(name='Other'), + self.randomGenerator("email"), + self.randomGenerator("randomNumber"), + self.randomGenerator("randomString"), + self.el, True) + + self.engagement.engagement_team.add(random_user) + self.engagement.save() + + users_list = [] + users_list.append(random_user) + activity_data = UserJoinedEngagementActivityData(self.vf, users_list, self.engagement) + bus_service.send_message(ActivityEventMessage(activity_data)) + + token = self.loginAndCreateSessionToken(random_user) + response = self.c.put(self.urlStr.replace("@stage", EngagementStage.Active.name), + json.dumps(dict(), ensure_ascii=False), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + token}) + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + + urlStr = self.urlPrefix + 'engagement/${uuid}/activities/' + response = self.c.get(urlStr.replace('${uuid}', str(self.engagement.uuid)), + **{'HTTP_AUTHORIZATION': "token " + token}) + content = json.loads(response.content) + self.assertEqual(len(content), 2) + + message = DailyScheduledMessage() + bus_service.send_message(message) + self.assertTrue(self.is_digested_mock_sent) + self.assertEqual(self.message, message) diff --git a/django/engagementmanager/tests/test_eng_progress.py b/django/engagementmanager/tests/test_eng_progress.py new file mode 100755 index 0000000..563c3cd --- /dev/null +++ b/django/engagementmanager/tests/test_eng_progress.py @@ -0,0 +1,99 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.status import HTTP_401_UNAUTHORIZED, HTTP_202_ACCEPTED, HTTP_500_INTERNAL_SERVER_ERROR +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class EngProgressTestCase(TestBaseEntity): + + def childSetup(self): # Variables to use in this class. + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + # Create a user with role standard_user + self.user = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + # Create an Engagement with team + self.engagement = self.creator.createEngagement( + 'just-a-fake-uuid', 'Validation', None) + self.engagement.engagement_team.add(self.user, self.el_user) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.save() + self.token = self.loginAndCreateSessionToken(self.user) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + + def testSetProgress(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/progress' + + self.printTestName("START") + + logger.debug( + "action should fail (401), Only Engagement Lead can set Engagement Progress") + response = self.c.put(urlStr, '{ "progress" : 50 }', content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + response = self.c.put(urlStr, '{ "progress" : 50 }', content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + + response = self.c.put(urlStr, '{ "progress" : 101 }', content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_500_INTERNAL_SERVER_ERROR) + + self.printTestName("END") diff --git a/django/engagementmanager/tests/test_eng_status.py b/django/engagementmanager/tests/test_eng_status.py new file mode 100755 index 0000000..62f787d --- /dev/null +++ b/django/engagementmanager/tests/test_eng_status.py @@ -0,0 +1,161 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from uuid import uuid4 +from rest_framework.status import HTTP_401_UNAUTHORIZED, HTTP_200_OK +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class EngagementStatusTestCase(TestBaseEntity): + + def childSetup(self): # Variables to use in this class. + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.peer_review_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + # Create a user with role standard_user + self.user = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + self.user_not_team = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'user not team', self.standard_user, True) + # Create an Engagement with team + self.engagement = self.creator.createEngagement(uuid4(), 'Validation', None) + self.engagement.engagement_team.add(self.user, self.el_user) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_review_user + self.engagement.save() + self.token = self.loginAndCreateSessionToken(self.user) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + self.user_not_team_token = self.loginAndCreateSessionToken(self.user_not_team) + + urlStr = self.urlPrefix + 'engagements/${uuid}/status' + myjson = json.dumps({"description": "blah blah"}, ensure_ascii=False) + response = self.c.post(urlStr.replace('${uuid}', str(self.engagement.uuid)), myjson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + self.created_status = json.loads(response.content) + + def testPutStatus(self): + urlStr = self.urlPrefix + 'engagements/${uuid}/status' + + self.printTestName("START - testPutStatus") + + logger.debug("action should fail (401), Only Engagement Lead can set Engagement Progress") + + myjson = json.dumps( + {"eng_status_uuid": self.created_status['uuid'], "description": "blah2 blah2"}, ensure_ascii=False) + response = self.c.put(urlStr.replace('${uuid}', str(self.engagement.uuid)), myjson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + myjson = json.dumps( + {"eng_status_uuid": self.created_status['uuid'], "description": "blah2 blah2"}, ensure_ascii=False) + response = self.c.put(urlStr.replace('${uuid}', str(self.engagement.uuid)), myjson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + self.printTestName("END - testPutStatus") + + def testPostStatus(self): + urlStr = self.urlPrefix + 'engagements/${uuid}/status' + + self.printTestName("START - testPostStatus") + + logger.debug("action should fail (401), Only Engagement Lead can set Engagement Progress") + + myjson = json.dumps({"description": "blah blah"}, ensure_ascii=False) + response = self.c.post(urlStr.replace('${uuid}', str(self.engagement.uuid)), myjson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + logger.debug("action should fail (400), For fake engagement uuid") + myjson = json.dumps({"description": "blah blah"}, ensure_ascii=False) + response = self.c.post(urlStr.replace( + '${uuid}', str(uuid4())), myjson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + myjson = json.dumps({"description": "blah blah"}, ensure_ascii=False) + response = self.c.post(urlStr.replace('${uuid}', str(self.engagement.uuid)), myjson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + self.printTestName("END - testPostStatus") + + def testGetStatus(self): + urlStr = self.urlPrefix + 'engagements/${uuid}/status' + + self.printTestName("START - testGetStatus") + + response = self.c.get(urlStr.replace('${uuid}', str(self.engagement.uuid)), + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + logger.debug("action should fail (401), Only team members can get status") + + response = self.c.get(urlStr.replace('${uuid}', str( + self.engagement.uuid)), content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.user_not_team_token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + logger.debug("action should fail (401), Only existing eng_uuid cab ne fetched") + response = self.c.get(urlStr.replace('${uuid}', str( + uuid4())), content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + self.printTestName("END - testGetStatus") diff --git a/django/engagementmanager/tests/test_engagement_admin_operations.py b/django/engagementmanager/tests/test_engagement_admin_operations.py new file mode 100755 index 0000000..a50e49f --- /dev/null +++ b/django/engagementmanager/tests/test_engagement_admin_operations.py @@ -0,0 +1,306 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.models import Vendor, Engagement, IceUserProfile, \ + Checklist +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import EngagementStage, Constants +from rest_framework.status import HTTP_200_OK, HTTP_401_UNAUTHORIZED +import json +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class EngagementAdminOperationsTestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + self.el_user = self.creator.createUser(Vendor.objects.get(name=Constants.service_provider_company_name), + self.randomGenerator("main-vendor-email"), '55501000199', + 'el user', self.el, True) + self.second_el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), '55501000199', + 'el user2', self.el, True) + self.el_user_to_update = self.creator.createUser( + Vendor.objects.get(name=Constants.service_provider_company_name), + self.randomGenerator("main-vendor-email"), '55501000199', + 'el user 3', self.el, True) + self.user = self.creator.createUser(Vendor.objects.get(name='Other'), + self.randomGenerator("main-vendor-email"), '55501000199', + 'user', self.standard_user, True) + self.admin_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), Constants.service_provider_admin_mail, '55501000199', + 'admin user', self.admin, True) + + self.engagement = self.creator.createEngagement( + 'just-a-fake-uuid', 'Validation', None) + self.engagement.engagement_team.add( + self.user, self.el_user, self.second_el_user) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.second_el_user + self.engagement.save() + # Create a VF + self.deploymentTarget = self.creator.createDeploymentTarget(self.randomGenerator("randomString"), + self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), self.engagement, self.deploymentTarget, + False, Vendor.objects.get(name='Other')) + + self.userToken = self.loginAndCreateSessionToken(self.user) + self.elToken = self.loginAndCreateSessionToken(self.el_user) + self.elUserToUpdateToken = self.loginAndCreateSessionToken( + self.el_user_to_update) + self.adminToken = self.loginAndCreateSessionToken(self.admin_user) + + def testGetAllEls(self): + num_of_els = IceUserProfile.objects.filter(role=self.el).count() + urlStr = self.urlPrefix + 'users/engagementleads/' + print(urlStr) + self.printTestName("testGetAllEls [Start]") + logger.debug( + "action should success (200), and return all els exists in the system") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + data = json.loads(response.content) + self.assertEqual(len(data), num_of_els) + self.assertEqual(data[0]['full_name'] == 'el user 3' or data[ + 0]['full_name'] == 'el user', True) + self.assertEqual(data[1]['full_name'] == 'el user 3' or data[ + 1]['full_name'] == 'el user2', True) + self.printTestName("testGetAllEls [End]") + + def testArchiveEngagement(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/archive' + print(urlStr) + self.printTestName("testArchiveEngagement [Start]") + logger.debug("action should success (202), and archive the engagement") + response = self.c.put(urlStr, json.dumps({'reason': 'test_reason'}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + eng_object = Engagement.objects.get(uuid=self.engagement.uuid) + # @UndefinedVariable + self.assertEqual( + eng_object.engagement_stage, EngagementStage.Archived.name) + self.assertEqual(eng_object.archive_reason, 'test_reason') + self.printTestName("testArchiveEngagement [End]") + + def testArchiveEngagementValidateDate(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/archive' + print(urlStr) + self.printTestName("testArchiveEngagement [Start]") + logger.debug("action should success (202), and archive the engagement") + response = self.c.put(urlStr, json.dumps({'reason': 'test_reason'}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + eng_object = Engagement.objects.get(uuid=self.engagement.uuid) + self.assertEqual(eng_object.engagement_stage, + EngagementStage.Archived.name) # @UndefinedVariable + self.assertTrue(eng_object.archived_time) + print(eng_object.archived_time) + self.printTestName("testArchiveEngagement [End]") + + def testSetEngagementReviewer(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/reviewer/' + print(urlStr) + self.printTestName("testSetEngagementReviewer [Start]") + logger.debug( + "action should success (200), and set the engagement reviewer") + response = self.c.put(urlStr, json.dumps({'reviewer': str(self.el_user_to_update.uuid)}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + eng_object = Engagement.objects.get(uuid=self.engagement.uuid) + self.assertEqual( + eng_object.reviewer.uuid, str(self.el_user_to_update.uuid)) + self.printTestName("testSetEngagementReviewer [End]") + + def testSetEngagementPeerReviewer(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/peerreviewer/' + print(urlStr) + self.printTestName("testSetEngagementPeerReviewer [Start]") + logger.debug( + "action should success (200), and set the engagement peer reviewer") + response = self.c.put(urlStr, json.dumps({'peerreviewer': str(self.el_user_to_update.uuid)}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + eng_object = Engagement.objects.get(uuid=self.engagement.uuid) + self.assertEqual(eng_object.peer_reviewer.uuid, + str(self.el_user_to_update.uuid)) + self.printTestName("testSetEngagementPeerReviewer [End]") + + def testNegativeGetAllEls(self): + urlStr = self.urlPrefix + 'users/engagementleads/' + print(urlStr) + self.printTestName("testNegativeGetAllEls [Start]") + logger.debug("action should failed due to missing permissions (401)") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.elToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + self.printTestName("testNegativeGetAllEls [End]") + + def testNegativeArchiveEngagement(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/archive' + print(urlStr) + self.printTestName("testNegativeArchiveEngagement [Start]") + logger.debug("action should failed due to missing permissions (401)") + response = self.c.put(urlStr, json.dumps({'reason': 'test_reason'}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.elToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + self.printTestName("testNegativeArchiveEngagement [End]") + + def testNegativeSetEngagementReviewer(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/reviewer/' + print(urlStr) + self.printTestName("testNegativeSetEngagementReviewer [Start]") + logger.debug("action should failed due to missing permissions (401)") + response = self.c.put(urlStr, json.dumps({'reviewer': str(self.el_user_to_update.uuid)}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.elToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + self.printTestName("testNegativeSetEngagementReviewer [End]") + + def testNegativeSetEngagementPeerReviewer(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/peerreviewer/' + print(urlStr) + self.printTestName("testNegativeSetEngagementPeerReviewer [Start]") + logger.debug("action should failed due to missing permissions (401)") + response = self.c.put(urlStr, json.dumps({'peerreviewer': str(self.el_user_to_update.uuid)}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.elToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + self.printTestName("testNegativeSetEngagementPeerReviewer [End]") + + def testSwitchEngagementReviewers(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/switch-reviewers/' + print(urlStr) + self.printTestName("testSetEngagementReviewer [Start]") + logger.debug( + "action should success (200), and switch between the engagement reviewer and peer reviewer") + logger.debug("Reviewer: %s, PeerReviewer: %s" % + (self.engagement.reviewer, self.engagement.peer_reviewer)) + response = self.c.put(urlStr, json.dumps({'reviewer': str(self.second_el_user.uuid), 'peerreviewer': str( + self.el_user.uuid)}), content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + eng_object = Engagement.objects.get(uuid=self.engagement.uuid) + self.assertEqual( + eng_object.reviewer.uuid, str(self.second_el_user.uuid)) + self.assertEqual( + eng_object.peer_reviewer.uuid, str(self.el_user.uuid)) + logger.debug("Reviewer: %s, PeerReviewer: %s" % + (eng_object.reviewer, eng_object.peer_reviewer)) + self.printTestName("testSetEngagementReviewer [End]") + + def testChecklistOwnerAfterChangeReviewer(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/reviewer/' + print(urlStr) + self.printTestName("testChecklistOwnerAfterChangeReviewer [Start]") + cl_template = self.creator.createDefaultCheckListTemplate() + checklist = self.creator.createCheckList( + "cl-name", "review", 1, None, self.engagement, cl_template, + self.admin_user, self.el_user) + logger.debug( + "action should success (200), set the engagement reviewer and change checklist owner") + response = self.c.put(urlStr, json.dumps({'reviewer': str(self.el_user_to_update.uuid)}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + checklist = Checklist.objects.get(uuid=checklist.uuid) + self.assertEqual(checklist.owner, self.el_user_to_update) + self.printTestName("testChecklistOwnerAfterChangeReviewer [End]") + + def testChecklistOwnerAfterChangePeerReviewer(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/peerreviewer/' + print(urlStr) + self.printTestName("testChecklistOwnerAfterChangePeerReviewer [Start]") + cl_template = self.creator.createDefaultCheckListTemplate() + checklist = self.creator.createCheckList( + "cl-name", "peer_review", 1, None, self.engagement, cl_template, + self.admin_user, self.second_el_user) + logger.debug( + "action should success (200), set the engagement peer reviewer and change checklist owner") + response = self.c.put(urlStr, json.dumps({'peerreviewer': str(self.el_user_to_update.uuid)}), content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + checklist = Checklist.objects.get(uuid=checklist.uuid) + self.assertEqual(checklist.owner, self.el_user_to_update) + self.printTestName("testChecklistOwnerAfterChangePeerReviewer [End]") + + def testChecklistOwnerAfterSwitchReviewers(self): + urlStr = self.urlPrefix + 'engagements/' + \ + str(self.engagement.uuid) + '/switch-reviewers/' + print(urlStr) + self.printTestName("testChecklistOwnerAfterSwitchReviewers [Start]") + cl_template = self.creator.createDefaultCheckListTemplate() + checklist = self.creator.createCheckList( + "cl-name", "review", 1, None, self.engagement, cl_template, + self.admin_user, self.el_user) + logger.debug( + "action should success (200), switch between the engagement reviewer and peer reviewer and change checklist owner") + logger.debug("Reviewer: %s, PeerReviewer: %s" % + (self.engagement.reviewer, self.engagement.peer_reviewer)) + response = self.c.put(urlStr, json.dumps({'reviewer': str(self.second_el_user.uuid), 'peerreviewer': str( + self.el_user.uuid)}), content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.adminToken}) + print('Got response : ' + str(response.status_code)) + checklist = Checklist.objects.get(uuid=checklist.uuid) + self.assertEqual(checklist.owner, self.second_el_user) + self.printTestName("testChecklistOwnerAfterSwitchReviewers [End]") diff --git a/django/engagementmanager/tests/test_engagement_export.py b/django/engagementmanager/tests/test_engagement_export.py new file mode 100755 index 0000000..9cbceb0 --- /dev/null +++ b/django/engagementmanager/tests/test_engagement_export.py @@ -0,0 +1,161 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.status import HTTP_200_OK,\ + HTTP_500_INTERNAL_SERVER_ERROR +from engagementmanager.models import Vendor, ECOMPRelease +from engagementmanager.service.engagement_service import get_expanded_engs_for_export +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import EngagementStage, Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class EngagementExportTestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + self.admin = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), Constants.service_provider_admin_mail, + 'Aa123456', 'admin user', self.el, True) + self.user = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + 'Aa123456', 'user', self.standard_user, True) + + # Create an VF with Engagement (Active) - #1 + self.engagement = self.creator.createEngagement( + 'just-a-fake-uuid', 'Validation', None) + self.engagement.engagement_team.add(self.user, self.admin) + self.engagement.reviewer = self.admin + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.engagement_stage = EngagementStage.Active.name + self.engagement.save() + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), self.engagement, + self.deploymentTarget, False, Vendor.objects.get(name=Constants.service_provider_company_name)) + self.vf.ecomp_release = ECOMPRelease.objects.create( + uuid='uuid1', name='ActiveECOMPRelease') + self.vf.save() + + # Create an VF with Engagement (Intake) - #2 + self.engagement2 = self.creator.createEngagement( + 'just-a-fake-uuid2', 'Validation', None) + self.engagement2.engagement_team.add(self.user, self.admin) + self.engagement2.reviewer = self.admin + self.engagement2.peer_reviewer = self.peer_reviewer + self.engagement2.engagement_stage = EngagementStage.Intake.name + self.engagement2.save() + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf2 = self.creator.createVF(self.randomGenerator("randomString"), self.engagement2, + self.deploymentTarget, False, Vendor.objects.get(name='Other')) + self.vf2.ecomp_release = ECOMPRelease.objects.create( + uuid='uuid2', name='IntakeECOMPRelease') + self.vf2.save() + + self.token = self.loginAndCreateSessionToken(self.user) + self.adminToken = self.loginAndCreateSessionToken(self.admin) + + def testFailExport(self): + urlStr = self.urlPrefix + 'engagement/export/' + self.printTestName("Failed export [start]") + logger.debug( + "action should fail (500), missing arguments - stage and keyword") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_500_INTERNAL_SERVER_ERROR) + self.printTestName("Failed export [end]") + + def testSuccessExport(self): + self.printTestName("Success export [start]") + + urlStr = self.urlPrefix + 'engagement/export/?stage=Active&keyword' + logger.debug( + "action should success (200), and return one active engagement") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(len(response.content) > 0, True) + vfs, deployment_targets = get_expanded_engs_for_export( + "Active", "", self.user) + self.assertEqual(len(vfs) == 1, True) + self.assertEqual('ecomp_release__name' in vfs[0] and vfs[0] + ['ecomp_release__name'] == "ActiveECOMPRelease", True) + + urlStr = self.urlPrefix + 'engagement/export/?stage=Intake&keyword' + logger.debug( + "action should success (200), and return one intake engagement") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(len(response.content) > 0, True) + vfs, deployment_targets = get_expanded_engs_for_export( + "Intake", "", self.user) + self.assertEqual(len(vfs) == 1, True) + self.assertEqual('ecomp_release__name' in vfs[0] and vfs[0] + ['ecomp_release__name'] == "IntakeECOMPRelease", True) + + # Check keyword filtering: + urlStr = self.urlPrefix + 'engagement/export/?stage=All&keyword=Active' + logger.debug( + "action should success (200), and not return Intake engagement") + response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + self.assertEqual(len(response.content) > 0, True) + vfs, deployment_targets = get_expanded_engs_for_export( + "All", "Active", self.user) + self.assertEqual(len(vfs) == 0, True) + + # Check overview sheet data procedure: + logger.debug("Check if the store procedure return data as expected (suppose to return 4 rows of overview " + "sheet) and by that assume that it exists") + self.assertEqual(len(deployment_targets), 4) + + self.printTestName("Success export [end]") diff --git a/django/engagementmanager/tests/test_expanded_eng.py b/django/engagementmanager/tests/test_expanded_eng.py new file mode 100755 index 0000000..ec89d0b --- /dev/null +++ b/django/engagementmanager/tests/test_expanded_eng.py @@ -0,0 +1,325 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import random +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.models import Vendor, VF +from engagementmanager.utils.constants import Constants, EngagementStage +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class testGetExpandedEngsAndSearch(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + + self.createDefaultRoles() + # Create a user with role el + vendor = Vendor.objects.get(name=Constants.service_provider_company_name) + self.el_user = self.creator.createUser(vendor, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.el_user.uuid)) + print('Full Name: ' + self.el_user.full_name) + print('-----------------------------------------------------') + + # Create a user with role standard_user + self.vendor = Vendor.objects.get(name='Other') + self.user = self.creator.createUser(self.vendor, "Johnny@d2ice.com", self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user.uuid)) + print('Full Name: ' + self.user.full_name) + print('-----------------------------------------------------') + self.service_provider = Vendor.objects.get(name=Constants.service_provider_company_name) + self.peer_reviewer = self.creator.createUser(self.service_provider, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + logger.debug('-----------------------------------------------------') + logger.debug('Created Peer Reviewer:') + logger.debug('UUID: ' + str(self.peer_reviewer.uuid)) + logger.debug('Full Name: ' + self.peer_reviewer.full_name) + logger.debug('-----------------------------------------------------') + + # Create an Engagement with team + engStageList = [EngagementStage.Intake.name, EngagementStage.Active.name, + EngagementStage.Validated.name, EngagementStage.Completed.name] # @UndefinedVariable + self.random_stage = engStageList[(random.randint(0, 3) * 2 + 1) % 4] + self.names_array = list() + for i in range(0, 14): + self.engagement = self.creator.createEngagement( + self.randomGenerator("randomString"), self.randomGenerator("randomString"), None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.engagement_manual_id = self.randomGenerator( + "randomString") + self.engagement.engagement_team.add( + self.el_user, self.peer_reviewer) + self.engagement.engagement_stage = engStageList[( + random.randint(0, 3) * 2 + 1) % 4] + self.engagement.save() + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement.uuid)) + print('-----------------------------------------------------') + self.names_array.append(self.engagement.engagement_manual_id) + # Create a VF + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + # self.asInfrastructure = self.creator.createApplicationServiceInfrastructure(self.randomGenerator("randomString")) + self.vf = self.creator.createVF( + "vf_" + str(i), self.engagement, self.deploymentTarget, False, vendor) + self.vf.save() + self.names_array.append(self.vf.name) + print('-----------------------------------------------------') + print('Created VF:') + print('UUID: ' + str(self.vf.uuid)) + print('-----------------------------------------------------') + if (i % 2 == 0): + self.engagement.engagement_team.add(self.user) + vfc = self.creator.createVFC( + "vfc_" + str(i), self.randomGenerator("randomNumber"), self.vendor, self.vf, self.el_user) + self.names_array.append(vfc.name) + self.engagement.save() + + self.random_keyword = self.names_array[( + random.randint(0, len(self.names_array) - 1))] + self.token = self.loginAndCreateSessionToken(self.user) + + def loggerTestFailedOrSucceded(self, bool): + if bool: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test Succeeded") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + else: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug("Test failed") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + def test_get_expanded_even_numbered_engs_by_standard_user_no_keyword(self): + urlStr = self.urlPrefix + 'engagement/expanded/' + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Test started: test_get_expanded_even_numbered_engs_by_standard_user_no_keyword") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + postData = {'stage': 'All', 'keyword': '', 'offset': 0, 'limit': 15} + datajson = json.dumps(postData, ensure_ascii=False) + response = self.c.post( + urlStr, datajson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + status = response.status_code + logger.debug("Got response : " + str(status)) + if (status != 200): + logger.error("Got response : " + str(status) + + " , wrong http response returned ") + self.assertEqual(response.status_code, 200) + logger.debug("Got content : " + str(response.content)) + data = json.loads(response.content) + if (data['num_of_objects'] != 7): + self.loggerTestFailedOrSucceded(False) + logger.error( + "num of objects returned from server != 7 (all even numbers)") + self.assertEqual(data['num_of_objects'], 7) + for x in data['array']: + shortened_name = x['vf__name'].split('_') + if (int(shortened_name[1]) % 2 != 0): + self.loggerTestFailedOrSucceded(False) + logger.error("Odd VF name returned") + self.assertEqual(int(shortened_name[1]) % 2, 0) + self.loggerTestFailedOrSucceded(True) + + def test_get_expanded_engs_with_filter_no_keyword(self): + urlStr = self.urlPrefix + 'engagement/expanded/' + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Test started: test_get_expanded_engs_with_filter_no_keyword") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + postData = {'stage': self.random_stage, + 'keyword': '', 'offset': 0, 'limit': 15} + datajson = json.dumps(postData, ensure_ascii=False) + response = self.c.post( + urlStr, datajson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + status = response.status_code + logger.debug("Got response : " + str(status)) + if (status != 200): + logger.error("Got response : " + str(status) + + " , wrong http response returned ") + self.assertEqual(response.status_code, 200) + logger.debug("Got content : " + str(response.content)) + data = json.loads(response.content) + print("random stage chosen: " + self.random_stage) + for x in data['array']: + print("engagement's stage: " + x['engagement__engagement_stage']) + if (x['engagement__engagement_stage'] != self.random_stage): + self.loggerTestFailedOrSucceded(False) + logger.error( + "VF With different stage than defined filter was retrieved") + self.assertEqual( + x['engagement__engagement_stage'], self.random_stage) + self.loggerTestFailedOrSucceded(True) + + def test_get_expanded_engs_with_keyword_nofilter(self): + urlStr = self.urlPrefix + 'engagement/expanded/' + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Test started: test_get_expanded_engs_with_filter_no_keyword") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + postData = {'stage': 'All', 'keyword': self.random_keyword, + 'offset': 0, 'limit': 15} + datajson = json.dumps(postData, ensure_ascii=False) + response = self.c.post( + urlStr, datajson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + status = response.status_code + logger.debug("Got response : " + str(status)) + self.assertEqual(response.status_code, 200) + logger.debug("Got content : " + str(response.content)) + data = json.loads(response.content) + print("random keyword chosen: " + self.random_keyword) + for x in data['array']: + bool = False + if (x['engagement__engagement_manual_id'] != self.random_keyword and x['vf__name'] != self.random_keyword): + vf = VF.objects.get(engagement__uuid=x['engagement__uuid']) + urlStr = self.urlPrefix + 'vf/' + str(vf.uuid) + '/vfcs/' + vfc_of_x_response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + vfc_list = json.loads(vfc_of_x_response.content) + for vfc in vfc_list: + if vfc['name'] == self.random_keyword: + bool = True + break + else: + continue + else: + bool = True + if (not bool): + self.loggerTestFailedOrSucceded(False) + logger.error( + "VF With different stage than filter was retrieved") + self.assertEqual( + x['engagement__engagement_stage'], self.random_stage) + self.loggerTestFailedOrSucceded(True) + + def test_get_expanded_engs_with_keyword_and_filter(self): + urlStr = self.urlPrefix + 'engagement/expanded/' + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Test started: test_get_expanded_engs_with_filter_no_keyword") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + postData = {'stage': self.random_stage, + 'keyword': self.random_keyword, 'offset': 0, 'limit': 15} + datajson = json.dumps(postData, ensure_ascii=False) + response = self.c.post( + urlStr, datajson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + status = response.status_code + logger.debug("Got response : " + str(status)) + if (status != 200): + logger.error("Got response : " + str(status) + + " , wrong http response returned ") + self.assertEqual(response.status_code, 200) + logger.debug("Got content : " + str(response.content)) + data = json.loads(response.content) + print("random keyword chosen: " + self.random_keyword) + for x in data['array']: + bool = False + if (x['engagement__engagement_stage'] != self.random_stage): + self.loggerTestFailedOrSucceded(False) + logger.error( + "VF With different stage than defined filter was retrieved") + self.assertEqual( + x['engagement__engagement_stage'], self.random_stage) + if (x['engagement__engagement_manual_id'] != self.random_keyword and x['vf__name'] != self.random_keyword): + vf = VF.objects.get(engagement__uuid=x['engagement__uuid']) + urlStr = self.urlPrefix + 'vf' + str(vf.uuid) + '/vfcs/' + vfc_of_x_response = self.c.get( + urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + vfc_list = json.loads(vfc_of_x_response.content) + for vfc in vfc_list: + if (vfc['name'] == self.random_keyword): + bool = True + break + else: + continue + else: + bool = True + if (not bool): + self.loggerTestFailedOrSucceded(False) + logger.error( + "VF With different stage than filter was retrieved") + self.assertEqual( + x['engagement__engagement_stage'], self.random_stage) + self.loggerTestFailedOrSucceded(True) + + def test_get_expanded_engs_with_keyword_email(self): + urlStr = self.urlPrefix + 'engagement/expanded/' + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug( + " Test started: test_get_expanded_engs_with_filter_no_keyword") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + email_test = "Johnny@d2ice.com" + postData = {'stage': 'All', 'keyword': email_test, + 'offset': 0, 'limit': 15} + datajson = json.dumps(postData, ensure_ascii=False) + response = self.c.post( + urlStr, datajson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + status = response.status_code + logger.debug("Got response : " + str(status)) + self.assertEqual(response.status_code, 200) + logger.debug("Got content : " + str(response.content)) + data = json.loads(response.content) + print("random keyword chosen: " + email_test) + if data['num_of_objects'] >= 1: + for vf_record in data['array']: + vf = VF.objects.get( + engagement__uuid=vf_record['engagement__uuid']) + if (not vf.engagement.engagement_team.filter(uuid=self.user.uuid).exists()): + self.loggerTestFailedOrSucceded(False) + logger.error( + "VF With different stage than filter was retrieved") + self.loggerTestFailedOrSucceded(True) + else: + self.loggerTestFailedOrSucceded(False) diff --git a/django/engagementmanager/tests/test_import_engagement_xls.py b/django/engagementmanager/tests/test_import_engagement_xls.py new file mode 100755 index 0000000..8513998 --- /dev/null +++ b/django/engagementmanager/tests/test_import_engagement_xls.py @@ -0,0 +1,72 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from io import StringIO +import os + +from django.core import management + +from engagementmanager.management.commands.initial_populate_db import execute_bootstrap_actions +from engagementmanager.tests.test_base_entity import TestBaseEntity + + +class TestImportEngagementXLSTestCase(TestBaseEntity): + + def childSetup(self): + execute_bootstrap_actions() + pass + + def initBody(self): + pass + + ### TESTS ### + def testImportEngagementXLSTestCase(self): + self.initBody() + xls_path = 'engagementmanager/tests/D2_ICE_Engagements_Import_Example.xlsx' + + if not os.path.exists(xls_path): + print("File doesnt exists") + return True + + response = StringIO() + + management.call_command('import_xls', xls_path, '2', stdout=response) + response = response.getvalue() + if response.find('True') != -1: + response = True + self.assertEqual(response, True) diff --git a/django/engagementmanager/tests/test_invite_members.py b/django/engagementmanager/tests/test_invite_members.py new file mode 100755 index 0000000..460eded --- /dev/null +++ b/django/engagementmanager/tests/test_invite_members.py @@ -0,0 +1,164 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.tests.test_base_entity import TestBaseEntity +import json +from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST +from engagementmanager.models import Vendor, IceUserProfile +from engagementmanager.utils.constants import Constants + + +class TestInviteMembersTestCase(TestBaseEntity): + + def createEng(self, name): + # Create an Engagement with team + engagement = self.creator.createEngagement(name, 'Validation', None) + engagement.reviewer = self.reviewer + engagement.peer_reviewer = self.reviewer + engagement.save() + engagement.engagement_team.add(self.inviter, self.el_user) + self.engList.append(engagement) + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(engagement.uuid)) + print('-----------------------------------------------------') + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Other']) + + self.createDefaultRoles() + self.engList = [] + self.vfList = [] + + # Create a user with role el + self.el_user_email = self.randomGenerator("main-vendor-email") + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), + self.el_user_email, '55501000199', 'el user', self.el, True) + self.inviter = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'inviter user', self.standard_user, True) + self.reviewer = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'reviewer user', self.standard_user, True) + + self.createEng('123456789') + self.createEng('abcdefghi') + + # Create a VF + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + + for eng in self.engList: + vf = self.creator.createVF(self.randomGenerator("randomString"), eng, + self.deploymentTarget, False, Vendor.objects.get(name='Other')) + self.vfList.append(vf) + + self.urlStr = self.urlPrefix + "invite-team-members/" + self.data = dict() + self.data2 = dict() + self.token = self.loginAndCreateSessionToken(self.inviter) + + def initBody(self): + self.invitedData = [] + + self.data['email'] = self.randomGenerator("main-vendor-email") + self.data['eng_uuid'] = str(self.engList[0].uuid) + self.invitedData.append(self.data) + + self.data2['email'] = self.el_user_email + self.data2['eng_uuid'] = str(self.engList[0].uuid) + self.invitedData.append(self.data2) + + def inviteContact(self, expectedStatus=HTTP_200_OK): + self.invitedDataStr = json.dumps(self.invitedData, ensure_ascii=False) + response = self.c.post(self.urlStr, self.invitedDataStr, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code), str(response.content)) + self.assertEqual(response.status_code, expectedStatus) + return response + + def createContactUser(self): + self.contact = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.data['email'], self.data['phone_number'], self.data['full_name'], self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.contact.uuid)) + print('Full Name: ' + self.contact.full_name) + print('-----------------------------------------------------') + + ### TESTS ### + def testAddContactForNonExistingContact(self): + self.initBody() + self.inviteContact() + + def testThrotellingInviteSameEmailSameEng(self): + self.invitedData = [] + + self.data['email'] = self.el_user_email + self.data['eng_uuid'] = str(self.engList[0].uuid) + self.invitedData.append(self.data) + + self.data2['email'] = self.el_user_email + self.data2['eng_uuid'] = str(self.engList[0].uuid) + self.invitedData.append(self.data2) + + self.inviteContact(expectedStatus=HTTP_400_BAD_REQUEST) + + def testThrotellingInviteMoreThan5EmailsToSameEng(self): + self.invitedData = [] + + for i in range(0, 30): + data = dict() + data['email'] = self.randomGenerator("main-vendor-email") + data['eng_uuid'] = str(self.engList[0].uuid) + self.invitedData.append(data) + + self.inviteContact(expectedStatus=HTTP_400_BAD_REQUEST) + + def testMultipleInvitationsForSameUserDiffEng(self): + for i in range(0, 2): + data = dict() + data['email'] = self.el_user_email + data['eng_uuid'] = str(self.engList[i].uuid) + self.invitedData = [] + self.invitedData.append(data) + self.inviteContact(expectedStatus=HTTP_200_OK) + invitedUser = IceUserProfile.objects.get(email=data['email']) + self.assertTrue(invitedUser in self.engList[i].engagement_team.all()) diff --git a/django/engagementmanager/tests/test_next_steps.py b/django/engagementmanager/tests/test_next_steps.py new file mode 100755 index 0000000..95a8227 --- /dev/null +++ b/django/engagementmanager/tests/test_next_steps.py @@ -0,0 +1,80 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import unittest + +from mock import MagicMock + +from engagementmanager.service.nextstep_service import NextStepSvc +from engagementmanager.utils.constants import NextStepState + + +class NextStepTest(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def testStandardUserActions(self): + print('---------------------------------- Testing standard_user Actions ------------------------------------') + user = MagicMock() + user.role.name = 'standard_user' + + NextStepSvc().validate_state_transition( + user, NextStepState.Incomplete, NextStepState.Completed) + + NextStepSvc().validate_state_transition( + user, NextStepState.Completed, NextStepState.Incomplete) + + def testELUserActions(self): + print('---------------------------------- Testing EL Actions ------------------------------------') + user = MagicMock() + user.role.name = 'el' + + print(user.role) + + update_type = NextStepSvc().validate_state_transition( + user, NextStepState.Completed, NextStepState.Incomplete) + assert update_type == 'Denied' + + +if __name__ == "__main__": + # import sys;sys.argv = ['', 'Test.testSetState'] + unittest.main() diff --git a/django/engagementmanager/tests/test_next_steps_api.py b/django/engagementmanager/tests/test_next_steps_api.py new file mode 100755 index 0000000..b0be468 --- /dev/null +++ b/django/engagementmanager/tests/test_next_steps_api.py @@ -0,0 +1,367 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from uuid import uuid4 + +from rest_framework import status +from rest_framework.status import HTTP_403_FORBIDDEN, HTTP_200_OK, \ + HTTP_204_NO_CONTENT + +from engagementmanager.models import Vendor, NextStep +from engagementmanager.service.nextstep_service import NextStepSvc +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants + + +class TestNextStepsAPI(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + + self.createDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.el_user.uuid)) + print('Full Name: ' + self.el_user.full_name) + print('-----------------------------------------------------') + + # Create a user with role standard_user + self.user = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user.uuid)) + print('Full Name: ' + self.user.full_name) + print('-----------------------------------------------------') + + # Create a user with role standard_user + self.pruser = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.pruser.uuid)) + print('Full Name: ' + self.pruser.full_name) + print('-----------------------------------------------------') + + # Create a user with role standard_user with SSH key + self.user_with_ssh = self.creator.createUser(Vendor.objects.get( + name='Other'), self.randomGenerator("main-vendor-email"), + '55501000199', 'ssh user', self.standard_user, True, 'just-a-fake-ssh-key') + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user_with_ssh.uuid)) + print('Full Name: ' + self.user_with_ssh.full_name) + print('-----------------------------------------------------') + + # Create an Engagement with team + self.engagement = self.creator.createEngagement('just-a-fake-uuid', 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.el_user + self.engagement.engagement_team.add(self.user, self.el_user) + self.engagement.save() + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement.uuid)) + print('-----------------------------------------------------') + + # Create another Engagement with team with SSH Key + self.engagement_ssh = self.creator.createEngagement('just-another-fake-uuid', 'Validation', None) + self.engagement_ssh.engagement_team.add(self.user_with_ssh, self.el_user) + self.engagement_ssh.peer_reviewer = self.pruser + self.engagement_ssh.save() + + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement_ssh.uuid)) + print('-----------------------------------------------------') + + # Create another Engagement with Main Contact + self.engagement_with_contact = self.creator.createEngagement('yet-just-another-fake-uuid', 'Validation', None) + self.engagement_with_contact.engagement_team.add(self.user, self.el_user) + self.engagement_with_contact.contact_user = self.user + self.engagement_with_contact.peer_reviewer = self.pruser + self.engagement_with_contact.save() + + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement_with_contact.uuid)) + print('-----------------------------------------------------') + + # Create another Engagement with Main Contact + self.engagement_4_createNS = self.creator.createEngagement('yet-just-another-fake-uuid2', 'Validation', None) + self.engagement_4_createNS.reviewer = self.el_user + self.engagement_4_createNS.peer_reviewer = self.el_user + self.engagement_4_createNS.engagement_team.add(self.user_with_ssh, self.el_user) + self.engagement_4_createNS.contact_user = self.user_with_ssh + self.engagement_4_createNS.save() + + # Create engagement for order + self.engagement_4_order = self.creator.createEngagement('yet-just-another-fake-uuid3', 'Validation', None) + self.engagement_4_order.reviewer = self.el_user + self.engagement_4_order.peer_reviewer = self.el_user + self.engagement_4_order.engagement_team.add(self.user_with_ssh, self.el_user) + self.engagement_4_order.contact_user = self.user_with_ssh + self.engagement_4_order.save() + + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vendor = Vendor.objects.get(name='Other') + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement_4_createNS, self.deploymentTarget, False, self.vendor) + + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement_4_createNS.uuid)) + print('-----------------------------------------------------') + + self.token = self.loginAndCreateSessionToken(self.user) + self.sshtoken = self.loginAndCreateSessionToken(self.user_with_ssh) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + + def testCreateDefaultNextStepsAndSetNextStepsState(self): + urlStr = self.urlPrefix + 'engagements/${uuid}/nextsteps/Intake' + NextStepSvc().create_default_next_steps(self.user, self.engagement, self.el_user) + NextStepSvc().create_default_next_steps_for_user(self.user, self.el_user) + num_of_steps = 3 + + response = self.c.get(urlStr.replace('${uuid}', str(self.engagement.uuid)), + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + print("DATA After JSON Parse:" + str(response.content)) + +# content = response.content + + print('Test that GET nextsteps was successful') + self.assertEqual(response.status_code, HTTP_200_OK) + + print('Test that GET nextsteps in Intake state returns 3 items ') + self.assertEqual(len(response.json()), num_of_steps) + + print('Test First item state is Incomplete: ' + response.json()[0]['state']) + self.assertEqual(response.json()[0]['state'], 'Incomplete') + + step_uuid = response.json()[0]['uuid'] + urlStr = self.urlPrefix + 'nextsteps/' + step_uuid + '/state' + + print('attempt change state of next step Incomplete->COMPLETED by standard_user. This should succeed...') + response = self.c.put(urlStr, '{ "state" : "Completed" }', + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + print('Negative: attempt change state of next step COMPLETED->Incomplete by EL. This should success') + response = self.c.put(urlStr, '{ "state" : "Incomplete" }', + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + def testCreateDefaultNextStepsForUserWithSSHKey(self): + urlStr = self.urlPrefix + 'engagements/${uuid}/nextsteps/Intake' + NextStepSvc().create_default_next_steps(self.user_with_ssh, self.engagement_ssh, self.el_user) + # Would not create any next step, due to the reason that the user already has an SSH + NextStepSvc().create_default_next_steps_for_user(self.user_with_ssh, self.el_user) + num_of_steps = 2 + + response = self.c.get(urlStr.replace('${uuid}', str(self.engagement_ssh.uuid)), + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + print("DATA After JSON Parse:" + str(response.content)) + + print('Test that GET nextsteps was successful') + self.assertEqual(response.status_code, HTTP_200_OK) + + print('Test that GET nextsteps in Intake state returns 3 items ') + self.assertEqual(len(response.json()), num_of_steps) + + def testOrderNextSteps(self): + + nsDict = {} + nsDict["position"] = 4 + nsDict["creator_uuid"] = str(self.el_user.uuid) + nsDict[ + "description"] = "Please submit the first version of the VF package. If you have any problems or questions please contact your Engagement Lead (EL)" + nsDict["state"] = "Incomplete" + nsDict["engagement_stage"] = "Active" + + myjson = json.dumps([nsDict], ensure_ascii=False) + + create_nextsteps_url = self.urlPrefix + "engagements/" + str(self.engagement_4_order.uuid) + "/nextsteps/" + response = self.c.post(create_nextsteps_url, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + response = self.c.post(create_nextsteps_url, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + response = self.c.post(create_nextsteps_url, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + + get_nextsteps_url = self.urlPrefix + 'engagements/${uuid}/nextsteps/Intake' + response = self.c.get(get_nextsteps_url.replace('${uuid}', str( + self.engagement_4_order.uuid)), **{'HTTP_AUTHORIZATION': "token " + self.sshtoken}) + + decoded_ns = json.loads(response.content) + myjson = json.dumps(decoded_ns, ensure_ascii=False) + order_nextsteps_url = self.urlPrefix + 'engagements/' + \ + str(self.engagement_4_order.uuid) + '/nextsteps/order_next_steps/' + response = self.c.put(order_nextsteps_url, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + + response = self.c.get(get_nextsteps_url.replace('${uuid}', str( + self.engagement_4_order.uuid)), **{'HTTP_AUTHORIZATION': "token " + self.sshtoken}) + + decoded_ns = json.loads(response.content) + counter = 0 + for next_step in decoded_ns: + self.assertEqual(next_step['position'], counter) + counter += 1 + + def testCreateDefaultNextStepsWhenENGContactExist(self): + urlStr = self.urlPrefix + 'engagements/${uuid}/nextsteps/Intake' + NextStepSvc().create_default_next_steps(self.user, self.engagement_with_contact, self.el_user) + NextStepSvc().create_default_next_steps_for_user(self.user, self.el_user) + num_of_steps = 2 + + response = self.c.get(urlStr.replace('${uuid}', str( + self.engagement_with_contact.uuid)), **{'HTTP_AUTHORIZATION': "token " + self.token}) + + print('Got response : ' + str(response.status_code)) + print("DATA After JSON Parse:" + str(response.content)) + + print('Test that GET nextsteps was successful') + self.assertEqual(response.status_code, HTTP_200_OK) + + print('Test that GET nextsteps in Intake state returns 3 items ') + self.assertEqual(len(response.json()), num_of_steps) + + def testAddNextStepToEng(self): + urlStr = self.urlPrefix + "engagements/" + str(self.engagement_4_createNS.uuid) + "/nextsteps/" + + NextStepSvc().create_default_next_steps(self.user_with_ssh, self.engagement_4_createNS, self.el_user) + # Would not create any next step, due to the reason that the user already has an SSH + NextStepSvc().create_default_next_steps_for_user(self.user_with_ssh, self.el_user) + + nsDict = {} + nsDict["position"] = "4" + nsDict["creator_uuid"] = str(self.el_user.uuid) + nsDict[ + "description"] = "Please submit the first version of the VF package. If you have any problems or questions please contact your Engagement Lead (EL)" + nsDict["state"] = "Incomplete" + nsDict["engagement_stage"] = "Active" + + myjson = json.dumps([nsDict], ensure_ascii=False) + print(myjson) + + response = self.c.post(urlStr, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + print("DATA After JSON Parse:" + str(response.content)) + + self.assertEqual(response.status_code, HTTP_200_OK) + + def testDelNextStepToEng(self): + nsObj = NextStep.objects.create(uuid=uuid4(), creator=self.el_user, position=2, description="testDelNextStepToEng", + state='Incomplete', engagement_stage="Intake", engagement=self.engagement) + urlStr = self.urlPrefix + "nextsteps/" + str(nsObj.uuid) + + response = self.c.delete(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + print("DATA After JSON Parse:" + str(response.content)) + + self.assertEqual(response.status_code, HTTP_204_NO_CONTENT) + + def testNegativeDelNextStepToEngNoHeader(self): + nsObj = NextStep.objects.create(uuid=uuid4(), creator=self.el_user, position=2, description="testDelNextStepToEng", + state='Incomplete', engagement_stage="Intake", engagement=self.engagement) + urlStr = self.urlPrefix + "nextsteps/" + str(nsObj.uuid) + + response = self.c.delete(urlStr) + print('Negative: Expecting response 403, got: ' + str(response.status_code)) + print("DATA After JSON Parse:" + str(response.content)) + + self.assertEqual(response.status_code, HTTP_403_FORBIDDEN) + + def testEditNextSteps(self): + print( + '---------------------------------- testEditNextSteps, Expecting 200 ------------------------------------') + print('---------------------------------- Creating a next step ------------------------------------') + step = NextStep.objects.create(position="4", creator=self.el_user, engagement=self.engagement, + description="Please submit the first version of the VF package. If you have any problems or questions please contact your Engagement Lead (EL)", + state="TODO", engagement_stage="Active", + uuid=uuid4()) + print('---------------------------------- Editing the next step ------------------------------------') + urlStr = self.urlPrefix + "nextsteps/" + str(step.uuid) + body = {} + files = [] + for i in range(4): + files.append(self.randomGenerator('randomString')) + body['files'] = files + body['duedate'] = "2012-01-03" + body['description'] = self.randomGenerator('randomString') + body['assigneesUuids'] = [str(self.user.uuid), str(self.el_user.uuid)] + myjson = json.dumps(body, ensure_ascii=False) + print(myjson) + response = self.c.put(urlStr, myjson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print(urlStr) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def testUserNextSteps(self): + NextStepSvc().create_default_next_steps(self.user_with_ssh, self.engagement_4_createNS, self.el_user) + # Needs to return 0 elements for regular user which is not the assignee: + urlStr = self.urlPrefix + 'engagements/user/nextsteps/' + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.sshtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + data = json.loads(response.content) + self.assertEqual(data["data"], []) + self.assertEqual(data["count"], 0) + + # Needs to return 3 elements to el user which is the assignee: + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + data = json.loads(response.content) + self.assertEqual(data["count"], 3) diff --git a/django/engagementmanager/tests/test_notify_inactive_engagements.py b/django/engagementmanager/tests/test_notify_inactive_engagements.py new file mode 100755 index 0000000..afeb835 --- /dev/null +++ b/django/engagementmanager/tests/test_notify_inactive_engagements.py @@ -0,0 +1,232 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import random +from uuid import uuid4 + +from django.utils.timezone import timedelta +import mock +from engagementmanager.tests.test_base_entity import TestBaseEntity + +from engagementmanager.apps import bus_service +from engagementmanager.bus.messages.daily_scheduled_message import DailyScheduledMessage +from engagementmanager.models import Vendor, Engagement, Activity, Notification +from engagementmanager.utils.constants import EngagementStage, ActivityType, Constants +from django.utils import timezone + + +def mocked_max_empty_date_negative(self, creation_time): + max_empty_time = creation_time + timedelta(days=-1) + return max_empty_time + + +def with_files(vf): + list_of_files = list() + for index in range(3): + current_file_dict = dict() + current_file_dict['id'] = ''.join(random.choice( + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(16)) + current_file_dict['name'] = 'file%d' % index + current_file_dict['type'] = 'blob' + current_file_dict['mode'] = '100644' + list_of_files.append(current_file_dict) + return list_of_files + + +def get_days_delta_plus_1(self, start_time, end_time): + end_time = end_time + timedelta(days=1) + return (end_time - start_time).days + + +def get_days_delta_plus_7(self, start_time, end_time): + end_time = end_time + timedelta(days=7) + return (end_time - start_time).days + + +def get_days_delta_plus_23(self, start_time, end_time): + end_time = end_time + timedelta(days=23) + return (end_time - start_time).days + + +def get_days_delta_plus_29(self, start_time, end_time): + end_time = end_time + timedelta(days=29) + return (end_time - start_time).days + + +def no_files(vf): + return [] + + +class TestNotifyInactiveEngagements(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs', 'Other']) + self.createDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + # For negative tests + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + self.urlStr = self.urlPrefix + "engagement/@eng_uuid/checklist/new/" + self.data = dict() + self.template = self.creator.createDefaultCheckListTemplate() +# self.engagement = Engagement.objects.create(uuid='just-a-fake-uuid',engagement_stage='Validation') + self.engagement = self.creator.createEngagement(uuid4(), 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.el_user + self.engagement.engagement_team.add(self.user) + self.engagement.engagement_manual_id = str(timezone.now().year) + "-1" + self.engagement.engagement_team.add(self.el_user) + self.engagement.engagement_stage = EngagementStage.Active.name + self.engagement.save() + self.vendor = Vendor.objects.get(name='Other') + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, self.vendor) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', with_files) + def testOnlyNotActiveEngagementsAreNotEffected(self): + self.engagement.engagement_stage = EngagementStage.Archived.name + self.engagement.save() + + bus_service.send_message(DailyScheduledMessage()) + updated_engagement = Engagement.objects.get(uuid=self.engagement.uuid) + + self.assertEqual(updated_engagement.is_with_files, False) + + @mock.patch('engagementmanager.bus.handlers.daily_notify_inactive_engagements_handler.DailyNotifyInactiveEngagementsHandler.get_max_empty_date', mocked_max_empty_date_negative) + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', no_files) + def testEngagementsWithouthFilesOlderThan30DaysAreArchive(self): + bus_service.send_message(DailyScheduledMessage()) + updated_engagement = Engagement.objects.get(uuid=self.engagement.uuid) + + self.assertEqual(updated_engagement.is_with_files, False) + self.assertEqual(updated_engagement.engagement_stage, EngagementStage.Archived.name) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', no_files) + def testEngagementsWithouthFilesYoungerThan30DaysNotArchive(self): + bus_service.send_message(DailyScheduledMessage()) + updated_engagement = Engagement.objects.get(uuid=self.engagement.uuid) + + self.assertEqual(updated_engagement.is_with_files, False) + self.assertEqual(updated_engagement.engagement_stage, EngagementStage.Active.name) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', no_files) + def testEngagementsWithouthFilesIsNotMarked(self): + bus_service.send_message(DailyScheduledMessage()) + updated_engagement = Engagement.objects.get(uuid=self.engagement.uuid) + + self.assertEqual(updated_engagement.is_with_files, False) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', with_files) + def testEngagementsWithoFilesNotSentEmail(self): + bus_service.send_message(DailyScheduledMessage()) + new_activity = Activity.objects.filter( + engagement=self.engagement, + activity_type=ActivityType.notice_empty_engagement.name + ) + self.assertEqual(0, len(new_activity)) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', no_files) + @mock.patch('engagementmanager.bus.handlers.daily_notify_inactive_engagements_handler.DailyNotifyInactiveEngagementsHandler.get_days_delta', get_days_delta_plus_1) + def testEngagementsWithoutFilesOneDayEmailNotSent(self): + bus_service.send_message(DailyScheduledMessage()) + new_activity = Activity.objects.filter( + engagement=self.engagement, + activity_type=ActivityType.notice_empty_engagement.name + ) + self.assertEqual(0, len(new_activity)) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', no_files) + @mock.patch('engagementmanager.bus.handlers.daily_notify_inactive_engagements_handler.DailyNotifyInactiveEngagementsHandler.get_days_delta', get_days_delta_plus_7) + def testEngagementsWithoutFiles7DayEmailSent(self): + bus_service.send_message(DailyScheduledMessage()) + new_activity = Activity.objects.get( + engagement=self.engagement, + activity_type=ActivityType.notice_empty_engagement.name + ) + + new_notifications = Notification.objects.filter(activity=new_activity) + self.assertNotEqual(0, len(new_notifications)) + + for notifcation in new_notifications: + self.assertEqual(notifcation.is_sent, True) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', no_files) + @mock.patch('engagementmanager.bus.handlers.daily_notify_inactive_engagements_handler.DailyNotifyInactiveEngagementsHandler.get_days_delta', get_days_delta_plus_23) + def testEngagementsWithoutFiles23DayEmailSent(self): + bus_service.send_message(DailyScheduledMessage()) + new_activity = Activity.objects.get( + engagement=self.engagement, + activity_type=ActivityType.notice_empty_engagement.name + ) + + new_notifications = Notification.objects.filter(activity=new_activity) + self.assertNotEqual(0, len(new_notifications)) + + for notifcation in new_notifications: + self.assertEqual(notifcation.is_sent, True) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', no_files) + @mock.patch('engagementmanager.bus.handlers.daily_notify_inactive_engagements_handler.DailyNotifyInactiveEngagementsHandler.get_days_delta', get_days_delta_plus_29) + def testEngagementsWithoutFiles29DayEmailSent(self): + bus_service.send_message(DailyScheduledMessage()) + new_activity = Activity.objects.get( + engagement=self.engagement, + activity_type=ActivityType.notice_empty_engagement.name + ) + + new_notifications = Notification.objects.filter(activity=new_activity) + self.assertNotEqual(0, len(new_notifications)) + + for notifcation in new_notifications: + self.assertEqual(notifcation.is_sent, True) + + @mock.patch('validationmanager.em_integration.vm_api.get_list_of_repo_files_callback', with_files) + def testEngagementsWithFilesIsMarked(self): + + bus_service.send_message(DailyScheduledMessage()) + updated_engagement = Engagement.objects.get(uuid=self.engagement.uuid) + + self.assertEqual(updated_engagement.is_with_files, True) diff --git a/django/engagementmanager/tests/test_pull_notifications.py b/django/engagementmanager/tests/test_pull_notifications.py new file mode 100755 index 0000000..1c22437 --- /dev/null +++ b/django/engagementmanager/tests/test_pull_notifications.py @@ -0,0 +1,134 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.apps import bus_service +from engagementmanager.bus.messages.activity_event_message import ActivityEventMessage +from engagementmanager.models import Vendor +from engagementmanager.utils.constants import Constants, ActivityType +from engagementmanager.utils.activities_data import ActivityData, UserJoinedEngagementActivityData +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class NotificationsTestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + + self.createDefaultRoles() + # Create a user with role el + vendor = Vendor.objects.get(name=Constants.service_provider_company_name) + self.peer_reviewer = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + self.el_user = self.creator.createUser(vendor, + self.randomGenerator("main-vendor-email"), + self.randomGenerator("randomNumber"), + self.randomGenerator("randomString"), self.el, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.el_user.uuid)) + print('Full Name: ' + self.el_user.full_name) + print('-----------------------------------------------------') + + # Create a user with role standard_user + vendor = Vendor.objects.get(name='Other') + self.user = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user.uuid)) + print('Full Name: ' + self.user.full_name) + print('-----------------------------------------------------') + + # Create an Engagement with team + self.engagement = self.creator.createEngagement(self.randomGenerator( + "randomString"), self.randomGenerator("randomString"), None) + self.engagement.engagement_team.add(self.user, self.el_user) + print('-----------------------------------------------------') + print('Created Engagement:') + print('UUID: ' + str(self.engagement.uuid)) + print('-----------------------------------------------------') + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + # Create a VF + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, vendor) + + print('-----------------------------------------------------') + print('Created VF:') + print('UUID: ' + str(vendor.uuid)) + print('-----------------------------------------------------') + + self.token = self.loginAndCreateSessionToken(self.user) + + def testPullNotifications(self): + + urlStr = self.urlPrefix + 'notifications/' + + logger.debug("Starting pull notification test") + logger.debug("Creating a random new user") + vendor = Vendor.objects.get(name='Other') + randomUser = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + self.engagement.engagement_team.add(randomUser) + self.engagement.save() + + logger.debug( + "created a new user & added them to the engagement team, going to create the activity and consider it as a notification") + usersList = [] + usersList.append(randomUser) + activity_data = UserJoinedEngagementActivityData( + self.vf, usersList, self.engagement) + bus_service.send_message(ActivityEventMessage(activity_data)) + + response = self.c.get(urlStr + str(randomUser.uuid) + + "/0/1", **{'HTTP_AUTHORIZATION': "token " + self.token}) + content = response.content + status = response.status_code + logger.debug("Got response : " + str(status)) + logger.debug("Got response : " + str(content)) + if (status != 200): + logger.error("Got response : " + str(status) + + " , wrong http response returned ") + self.assertEqual(response.status_code, 200) + logger.debug("Ended pullNotifications test ") diff --git a/django/engagementmanager/tests/test_rados_gateway.py b/django/engagementmanager/tests/test_rados_gateway.py new file mode 100755 index 0000000..0d81ecc --- /dev/null +++ b/django/engagementmanager/tests/test_rados_gateway.py @@ -0,0 +1,178 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +import time +from engagementmanager.tests.test_base_transaction_entity import TestBaseTransactionEntity +from django.test.testcases import TransactionTestCase +from django.conf import settings +import mock +from rest_framework.status import HTTP_202_ACCEPTED +from engagementmanager.models import Vendor, Engagement, VF +from engagementmanager.utils.constants import Constants, EngagementStage +from wheel.signatures import assertTrue + + +def get_or_create_bucket_mock(name): + bucket = {'bucket': name, + 'categories': [ + {'bytes_received': 0, + 'bytes_sent': 1388, + 'category': 'list_buckets', + 'ops': 4, + 'successful_ops': 4}], + 'epoch': 1499821200, + 'owner': 'staticfiles', + 'time': '2017-07-12 01:00:00.000000Z'} + + return bucket + + +def add_bucket_user_mock(user, bucket): + RadosGatewayTestCase.users_added_to_mock.append(user) + RadosGatewayTestCase.added_bucket = bucket + print("*****RadosGatewayTestCase.added_bucket*****",RadosGatewayTestCase.added_bucket) + + +def remove_bucket_user_grants_mock(bucket, user): + RadosGatewayTestCase.added_bucket = bucket + RadosGatewayTestCase.users_added_to_mock.remove(user) + + +def blank_mock(vf): + print("===--blank mock was activated--===") + pass + + +@mock.patch('validationmanager.em_integration.vm_api.get_or_create_bucket', get_or_create_bucket_mock) +@mock.patch('validationmanager.em_integration.vm_api.add_bucket_user', add_bucket_user_mock) +@mock.patch('validationmanager.em_integration.vm_api.remove_bucket_user_grants', remove_bucket_user_grants_mock) +@mock.patch('validationmanager.em_integration.vm_api.ensure_git_entities', blank_mock) +@mock.patch('validationmanager.em_integration.vm_api.ensure_jenkins_job', blank_mock) +@mock.patch('validationmanager.em_integration.vm_api.ensure_checklists', blank_mock) +class RadosGatewayTestCase(TestBaseTransactionEntity): + users_added_to_mock = [] + added_bucket = None + + def changeEngagementStage(self, stage): + self.urlStr = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + "/stage/@stage" + datajson = json.dumps(self.data, ensure_ascii=False) + response = self.c.put(self.urlStr.replace("@stage", stage), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + + def waitForBucket(self): + counter = 1 + while (RadosGatewayTestCase.added_bucket == None and counter <=20): + time.sleep(1) + time.sleep(1) + if RadosGatewayTestCase.added_bucket == None : + raise Exception("Max retries exceeded, failing test...") + return False + elif RadosGatewayTestCase.added_bucket != None: + return True + + def childSetup(self): + RadosGatewayTestCase.users_added_to_mock = [] + RadosGatewayTestCase.added_bucket = None + settings.IS_SIGNAL_ENABLED = True + self.s3_host = settings.AWS_S3_HOST + self.s3_port = settings.AWS_S3_PORT + + vendor_uuid, self.service_provider = self.creator.createVendor(Constants.service_provider_company_name) + self.urlStr = self.urlPrefix + "signup/" + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + + self.data = dict() + uuid, vendor = self.creator.createVendor(Constants.service_provider_company_name) + self.user = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + + self.params = '{"company":"' + str(self.user.company) + '","full_name":"' + self.user.full_name + '","email":"' \ + + self.user.email + '","phone_number":"' + self.user.phone_number + \ + '","password":"' + self.user.user.password + '","regular_email_updates":"' + \ + str(self.user.regular_email_updates) + \ + '","is_service_provider_contact":"' + str(self.user.is_service_provider_contact) + '"}' + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.peer_reviewer = self.creator.createUser(self.service_provider, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + + self.engagement = self.creator.createEngagement('just-a-fake-uuid', 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.engagement_team.add(self.el_user, self.user) + self.engagement.engagement_manual_id = self.randomGenerator("randomString") + self.engagement.save() + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, self.service_provider) + self.userToken = self.loginAndCreateSessionToken(self.user) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + + def testCreateBucketWithUser(self): + self.assertTrue(self.added_bucket is None) + self.changeEngagementStage(EngagementStage.Active.name) + self.assertTrue(RadosGatewayTestCase.added_bucket is not None) + team_members_list = [entry for entry in self.engagement.engagement_team.all()] + for team_member in team_members_list: + assertTrue(any(team_member.full_name == entity.full_name for entity in RadosGatewayTestCase.users_added_to_mock)) + + + def testDeleteUsersFromBucket(self): + self.changeEngagementStage(EngagementStage.Active.name) + self.changeEngagementStage(EngagementStage.Validated.name) + self.waitForBucket() + self.assertTrue(RadosGatewayTestCase.added_bucket is not None) + self.assertTrue(RadosGatewayTestCase.users_added_to_mock == []) + + def testDeleteUsersFromBucketWhichNotCreated(self): + self.assertTrue(RadosGatewayTestCase.added_bucket is None) + self.changeEngagementStage(EngagementStage.Validated.name) + self.waitForBucket() + self.assertTrue(RadosGatewayTestCase.added_bucket is not None) + self.assertTrue(RadosGatewayTestCase.users_added_to_mock == []) + + def testDeleteUsersFromBucketWhwenStageArchive(self): + self.assertTrue(RadosGatewayTestCase.added_bucket is None) + self.changeEngagementStage(EngagementStage.Archived.name) + self.waitForBucket() + self.assertTrue(RadosGatewayTestCase.added_bucket is not None) + self.assertTrue(RadosGatewayTestCase.users_added_to_mock == []) diff --git a/django/engagementmanager/tests/test_remove_user_from_eng_team.py b/django/engagementmanager/tests/test_remove_user_from_eng_team.py new file mode 100755 index 0000000..15bcf2d --- /dev/null +++ b/django/engagementmanager/tests/test_remove_user_from_eng_team.py @@ -0,0 +1,210 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from rest_framework.status import HTTP_204_NO_CONTENT +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class TestEngagementSetStage(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs']) + self.vendor = Vendor.objects.get(name='Amdocs') + self.service_provider = Vendor.objects.get(name=Constants.service_provider_company_name) + self.createDefaultRoles() + + # For negative tests + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + self.user2 = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user2', self.standard_user, True) + # Create users with role el (el+peer reviwer) + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.peer_reviewer = self.creator.createUser(self.service_provider, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + # Create a user with admin role + self.admin_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), Constants.service_provider_admin_mail, + '55501000199', 'admin user', self.admin, True) + + self.engagement = self.creator.createEngagement('just-a-fake-uuid', 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.engagement_team.add(self.el_user, self.user, self.user2) + self.engagement.save() + + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) +# self.asInfrastructure = self.creator.createApplicationServiceInfrastructure(self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, self.vendor) +# self.vf.service_infrastructures.add(self.asInfrastructure) + + self.data = dict() + self.user_token = self.loginAndCreateSessionToken(self.user) + self.user2_token = self.loginAndCreateSessionToken(self.user2) + self.admin_token = self.loginAndCreateSessionToken(self.admin_user) + + def loggerTestFailedOrSucceded(self, bool): + if bool: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test Succeeded") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + else: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug("Test failed") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + def test_remove_user_from_eng_team_by_admin(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test 2 started: Admin removes user from the eng team!") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.get_engagement_url = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + self.urlStr = self.urlPrefix + "engagements/engagement-team/" + self.data['eng_uuid'] = str(self.engagement.uuid) + self.data['user_uuid'] = str(self.user.uuid) + + datajson = json.dumps(self.data, ensure_ascii=False) + + logger.debug("**********************************************************************") + logger.debug("----- sending put request with body -----") + logger.debug("**********************************************************************") + + response = self.c.put(self.urlStr, datajson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + if (response.status_code != HTTP_204_NO_CONTENT): + print(response.status_code) + response2 = self.c.get(self.get_engagement_url, {}, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + + # Check if the user it still in the engagement team + received_eng = json.loads(response2.content) + found = False + for item in received_eng["engagement"]["engagement_team"]: + if (self.user.email == item["email"]): + found = True + break + if found: + self.loggerTestFailedOrSucceded(False) + self.assert_(False, "user is still in the eng_team") + else: + self.loggerTestFailedOrSucceded(True) + + def test_negative_remove_user_from_eng_team_by_another_user(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test 3 (Negative) started: User2 removes user1 from the eng team!") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.get_engagement_url = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + self.urlStr = self.urlPrefix + "engagements/engagement-team/" + self.data['eng_uuid'] = str(self.engagement.uuid) + self.data['user_uuid'] = str(self.user.uuid) + + datajson = json.dumps(self.data, ensure_ascii=False) + + logger.debug("**********************************************************************") + logger.debug("----- sending put request with body -----") + logger.debug("**********************************************************************") + + response = self.c.put(self.urlStr, datajson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.user2_token}) + if (response.status_code != HTTP_204_NO_CONTENT): + print(response.status_code) + response2 = self.c.get(self.get_engagement_url, {}, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + + # Check if the user it still in the engagement team(it is supposed to remain there) + received_eng = json.loads(response2.content) + found = False + for item in received_eng["engagement"]["engagement_team"]: + if (self.user.email == item["email"]): + found = True + break + if not found: + self.loggerTestFailedOrSucceded(False) + self.assert_(False, "user is NOT in the eng_team") + else: + self.loggerTestFailedOrSucceded(True) + + def test_negative_remove_el_user_from_eng_team_by_admin(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test 4 (Negative) started: admin removes el_user from the eng team!") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.get_engagement_url = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + self.urlStr = self.urlPrefix + "engagements/engagement-team/" + self.data['eng_uuid'] = str(self.engagement.uuid) + self.data['user_uuid'] = str(self.el_user.uuid) + + datajson = json.dumps(self.data, ensure_ascii=False) + + logger.debug("**********************************************************************") + logger.debug("----- sending put request with body -----") + logger.debug("**********************************************************************") + + response = self.c.put(self.urlStr, datajson, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + if (response.status_code != HTTP_204_NO_CONTENT): + print(response.status_code) + response2 = self.c.get(self.get_engagement_url, {}, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + + # Check if the user it still in the engagement team(it is supposed to remain there) + received_eng = json.loads(response2.content) + found = False + for item in received_eng["engagement"]["engagement_team"]: + if (self.el_user.email == item["email"]): + found = True + break + if not found: + self.loggerTestFailedOrSucceded(False) + self.assert_(False, "el user was NOT found in the eng_team") + else: + self.loggerTestFailedOrSucceded(True) diff --git a/django/engagementmanager/tests/test_request_data_manager.py b/django/engagementmanager/tests/test_request_data_manager.py new file mode 100755 index 0000000..580301e --- /dev/null +++ b/django/engagementmanager/tests/test_request_data_manager.py @@ -0,0 +1,205 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from concurrent.futures import ThreadPoolExecutor +import json +from random import randint +import threading +import time +from django.db import connections +from django.test.client import Client +from django.test.testcases import TransactionTestCase +from rest_framework.status import HTTP_401_UNAUTHORIZED, HTTP_200_OK +from engagementmanager.models import Vendor +from engagementmanager.tests.vvpEntitiesCreator import VvpEntitiesCreator +from engagementmanager.utils.authentication import JWTAuthentication +from engagementmanager.utils.constants import Constants +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class TestRequestDataManager(TransactionTestCase): + + def childSetup(self): + logger.debug("---------------------- TestCase " + self.__class__.__name__ + " ----------------------") + self.urlPrefix = "/ice/v1/engmgr/" + self.c = Client() + self.creator = VvpEntitiesCreator() + + for vendor in [Constants.service_provider_company_name, 'Other']: + vendorUuid, vendor = self.creator.createVendor(vendor) + logger.debug(vendorUuid) + + self.admin, self.el, self.standard_user = self.creator.createAndGetDefaultRoles() + + # Create a user with role el + self.el_user = self.creator.createUser( + Vendor.objects.get(name=Constants.service_provider_company_name), self.creator.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.peer_review_user = self.creator.createUser( + Vendor.objects.get(name=Constants.service_provider_company_name), self.creator.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + # Create a user with role standard_user + self.user = self.creator.createUser( + Vendor.objects.get(name='Other'), self.creator.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + self.user_not_team = self.creator.createUser( + Vendor.objects.get(name='Other'), self.creator.randomGenerator("main-vendor-email"), + '55501000199', 'user2', self.standard_user, True) +# # Create an Engagement with team + self.engagement = self.creator.createEngagement('just-a-fake-uuid', 'Validation', None) + self.engagement.engagement_team.add(self.user, self.el_user) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_review_user + self.engagement.save() + + self.jwt_service = JWTAuthentication() + self.token = self.jwt_service.create_token(self.user.user) + self.ELtoken = self.jwt_service.create_token(self.el_user.user) + + urlStr = self.urlPrefix + 'engagements/${uuid}/status' + myjson = json.dumps({"description": "blah blah"}, ensure_ascii=False) + response = self.c.post(urlStr.replace('${uuid}', str( + self.engagement.uuid)), myjson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + self.created_status = json.loads(response.content) + + def my_task(self, eng_id): + thread_local_id = threading.currentThread().ident + + # Inject an attribute into request data + request_data_mgr.set_eng_uuid(eng_id) + + # Inject thread id into requeat data + request_data_mgr.set_cl_uuid(thread_local_id) + + return self.my_inner_funcion(eng_id) + + def my_inner_funcion(self, eng_id): + thread_local_id = threading.currentThread().ident + + assert request_data_mgr.get_request_data() + + assert request_data_mgr.get_request_data()._eng_uuid == eng_id + assert request_data_mgr.get_eng_uuid() == eng_id + + # Checks that the allocated thread from testRequestDataManager is the same thread running in inner function + assert request_data_mgr.get_request_data()._cl_uuid == thread_local_id + assert request_data_mgr.get_cl_uuid() == thread_local_id + + print('thread: ' + str(thread_local_id) + '. request data : ' + str(request_data_mgr.get_request_data_vars())) + return "OK" + + def lauchTests(self): + executor = ThreadPoolExecutor(max_workers=10) + + for i in range(0, 100): + future1 = executor.submit(self.my_task, "eng#" + str(i)) + assert future1.result() == "OK" + + ########### TESTS ########### + + def testRequestDataManager(self): + executor = ThreadPoolExecutor(max_workers=2) + executor.submit(self.lauchTests) + executor.submit(self.lauchTests) + + def testMultipleRequestsInParallel(self): + self.childSetup() + number_of_concurrent_requests = 10 + executor = ThreadPoolExecutor(max_workers=number_of_concurrent_requests) + + def close_db_connections(func, *args, **kwargs): + """ + Decorator to explicitly close db connections during threaded execution + + Note this is necessary to work around: + https://code.djangoproject.com/ticket/22420 + """ + def _close_db_connections(*args, **kwargs): + ret = None + try: + ret = func(*args, **kwargs) + finally: + for conn in connections.all(): + logger.debug("Closing DB connection. connection=" + str(conn)) + conn.close() + return ret + return _close_db_connections + + @close_db_connections + def invokeRequest(metadata, token): + urlStr = self.urlPrefix + 'engagements/${uuid}/status' + + logger.debug("START - " + metadata) + + myjson = json.dumps( + {"eng_status_uuid": self.created_status['uuid'], "description": "blah2 blah2"}, ensure_ascii=False) + response = self.c.put(urlStr.replace('${uuid}', str( + self.engagement.uuid)), myjson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + + time.sleep(randint(0, 1)) + + myjson = json.dumps( + {"eng_status_uuid": self.created_status['uuid'], "description": "blah2 blah2"}, ensure_ascii=False) + response = self.c.put(urlStr.replace('${uuid}', str( + self.engagement.uuid)), myjson, content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + token}) + print('Got response : ' + str(response.status_code)) + self.assertEqual(response.status_code, HTTP_200_OK) + + logger.debug("END - " + metadata) + + return metadata + + for i in range(0, number_of_concurrent_requests): + eluser = self.creator.createUser( + Vendor.objects.get(name='Other'), self.creator.randomGenerator("main-vendor-email"), + '55501000199', 'user' + str(i), self.el, True) + token = self.jwt_service.create_token(eluser.user) + self.engagement = self.creator.createEngagement('just-a-fake-uuid', 'Validation', None) + self.engagement.engagement_team.add(eluser) + self.engagement.reviewer = eluser + self.engagement.peer_reviewer = self.peer_review_user + self.engagement.save() + + metadata = "test " + str(i) + future = executor.submit(invokeRequest, metadata, token) + assert future.result() == metadata diff --git a/django/engagementmanager/tests/test_resend_activation_email.py b/django/engagementmanager/tests/test_resend_activation_email.py new file mode 100755 index 0000000..b544001 --- /dev/null +++ b/django/engagementmanager/tests/test_resend_activation_email.py @@ -0,0 +1,62 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants + + +class TestResendActivationEmail(TestBaseEntity): + + def childSetup(self): + self.createDefaultRoles() + uuid, vendor = self.creator.createVendor(Constants.service_provider_company_name) + self.user = self.creator.createUser(vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, False) + self.urlStr = self.urlPrefix + \ + "users/activation-mail/" + self.user.uuid + self.params = {"email": self.user.email} + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user.uuid)) + print('Full Name: ' + self.user.full_name) + print('-----------------------------------------------------') + + def test_resend_activation_email(self): + response = self.c.get( + self.urlStr, self.params, content_type='application/json') + self.assertTrue(response.status_code, "200") diff --git a/django/engagementmanager/tests/test_reset_password.py b/django/engagementmanager/tests/test_reset_password.py new file mode 100755 index 0000000..7cfdd54 --- /dev/null +++ b/django/engagementmanager/tests/test_reset_password.py @@ -0,0 +1,75 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.models import Vendor +from engagementmanager.utils.constants import Constants + + +class TestResetPasswordTestCase(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs']) + self.createDefaultRoles() + + # Create a user with role el + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + + self.urlStr = self.urlPrefix + "users/pwd/sendresetinstr/" + self.data = dict() + self.token = self.loginAndCreateSessionToken(self.user) + + def initBody(self): + self.data['email'] = self.user.email + + def resetPwd(self, expectedStatus=200, httpMethod="PUT"): + self.accountData = json.dumps(self.data, ensure_ascii=False) + if (httpMethod == "PUT"): + response = self.c.put(self.urlStr, self.accountData, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + elif (httpMethod == "POST"): + response = self.c.post(self.urlStr, self.accountData, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code) + " Expecting " + str(expectedStatus)) + self.assertEqual(response.status_code, expectedStatus) + return response diff --git a/django/engagementmanager/tests/test_rgwa_client.py b/django/engagementmanager/tests/test_rgwa_client.py new file mode 100755 index 0000000..a65f5b3 --- /dev/null +++ b/django/engagementmanager/tests/test_rgwa_client.py @@ -0,0 +1,214 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.utils.constants import Constants +from validationmanager.rados.rgwa_client import _validate_args, RGWAClient + + +try: + from unittest.mock import patch, ANY +except ImportError: + from mock import patch, ANY + +try: + from unittest import assertRaises, expectedFailure +except ImportError: + from pytest import raises as assertRaises + from pytest import mark + expectedFailure = mark.xfail + + +class Test_ValidateArgs(object): + + def setup(self): + self.valid_args = { + 'foo': ['foo1', 'foo2'], + 'bar': [1, 2, 3], + } + + def test_unconstrained(self): + _validate_args(self.valid_args, baz="quux") + + def test_none_value(self): + _validate_args(self.valid_args, foo=None) + + def test_good_value(self): + _validate_args(self.valid_args, foo="foo1") + + def test_bad_value_raises(self): + with assertRaises(ValueError): + _validate_args(self.valid_args, foo="foo3") + + +@patch('ice_rgwa_client.request') +class TestRGWAClientMethods(object): + """Tests that all the methods invoke requests.request() with the + appropriate arguments. + + """ + + def setup(self): + self.access_key = 'ABCDEFGHIJKLMNOPQRST' + self.secret_key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn' + self.conn = RGWAClient( + access_key=self.access_key, + secret_key=self.secret_key, + base_url=Constants.rgwa_base_url + ) + + def test_get_usage(self, r): + self.conn.get_usage(uid='foo', show_entries=True) + r.assert_called_once_with( + auth=ANY, + method='get', + json={}, + params={'show-entries': True, 'show-summary': False, 'uid': 'foo'}, + url=Constants.rgwa_base_url+'/usage', + verify=True, + ) + + def test_trim_usage(self, r): + self.conn.trim_usage(uid='foo', remove_all=True) + r.assert_called_once_with( + auth=ANY, + method='delete', + json={}, + params={'remove-all': True, 'uid': 'foo'}, + url='http://localhost:8123/admin/usage', + verify=True, + ) + + def test_get_user(self, r): + self.conn.get_user(uid='foo') + r.assert_called_once_with( + auth=ANY, + method='get', + json={}, + params={'uid': 'foo'}, + url=Constants.rgwa_base_url+'/user', + verify=True, + ) + + # Marked FIXME because we experience diminishing returns here. All the + # methods in the library are basically one-liner calls to the common + # _request method, which has been sufficiently covered. There's no + # additional business logic that would be tested, only ensuring beyond api + # stability. Time would be better spent figuring out how to get tox to + # stand up testing instances of various versions of an actual radosgw + # server for integration testing. + + @expectedFailure + def test_create_user(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_modify_user(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_remove_user(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_create_subuser(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_modify_subuser(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_remove_subuser(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_create_key(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_remove_key(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_get_bucket(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_check_bucket_index(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_remove_bucket(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_unlink_bucket(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_link_bucket(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_remove_object(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_get_policy(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_add_capability(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_remove_capability(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_get_quota(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_set_quota(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_get_user_quota(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_set_user_quota(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_get_user_bucket_quota(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_set_user_bucket_quota(self, r): + raise NotImplementedError # FIXME + + @expectedFailure + def test_get_users(self, r): + raise NotImplementedError # FIXME + @expectedFailure + def test_get_buckets(self, r): + raise NotImplementedError # FIXME + + +# FIXME TODO Add integration tests against a local ceph radosgw instance, +# (disabled by default). Record result of test suite in repository. diff --git a/django/engagementmanager/tests/test_set_checklist_state.py b/django/engagementmanager/tests/test_set_checklist_state.py new file mode 100755 index 0000000..54d3c8e --- /dev/null +++ b/django/engagementmanager/tests/test_set_checklist_state.py @@ -0,0 +1,236 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.models import Vendor, Checklist, ChecklistDecision, \ + ChecklistLineItem, ChecklistSection +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import CheckListLineType, \ + CheckListDecisionValue, CheckListState, ChecklistDefaultNames, Constants +from rest_framework.status import HTTP_200_OK +from uuid import uuid4 +import json +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class TestChecklistSetState(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Amdocs']) + self.vendor = Vendor.objects.get(name='Amdocs') + self.createDefaultRoles() + + # For negative tests + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + # Create users with role el (el+peer reviwer) + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.peer_review_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'peer-reviewer user', self.el, True) + # Create a user with admin role + self.admin_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), Constants.service_provider_admin_mail, + '55501000199', 'admin user', self.admin, True) + + self.template = self.creator.createDefaultCheckListTemplate() + self.engagement = self.creator.createEngagement( + 'just-a-fake-uuid', 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_review_user + self.engagement.engagement_team.add(self.el_user, self.user) + self.engagement.save() + + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) +# self.asInfrastructure = self.creator.createApplicationServiceInfrastructure(self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, self.vendor) +# self.vf.service_infrastructures.add(self.asInfrastructure) + + self.clbodydata = dict() + self.initCLBody() + self.checklist = Checklist.objects.create(uuid=uuid4(), name=self.clbodydata['checkListName'], validation_cycle=1, associated_files=self.clbodydata[ + 'checkListAssociatedFiles'], engagement=self.engagement, template=self.template, creator=self.el_user, owner=self.el_user) + self.checklist.save() + self.section = ChecklistSection.objects.create(uuid=uuid4(), name=self.randomGenerator("randomString"), weight=1.0, description=self.randomGenerator( + "randomString"), validation_instructions=self.randomGenerator("randomString"), template=self.template) + self.section.save() + self.line_item = ChecklistLineItem.objects.create(uuid=uuid4(), name=self.randomGenerator("randomString"), weight=1.0, description=self.randomGenerator( + "randomString"), line_type=CheckListLineType.auto.name, validation_instructions=self.randomGenerator("randomString"), template=self.template, section=self.section) # @UndefinedVariable + self.line_item2 = ChecklistLineItem.objects.create(uuid=uuid4(), name=self.randomGenerator("randomString"), weight=1.0, description=self.randomGenerator( + "randomString"), line_type=CheckListLineType.auto.name, validation_instructions=self.randomGenerator("randomString"), template=self.template, section=self.section) # @UndefinedVariable + self.line_item.save() + self.line_item2.save() + self.decision = ChecklistDecision.objects.create( + uuid=uuid4(), checklist=self.checklist, template=self.template, lineitem=self.line_item) + self.decision2 = ChecklistDecision.objects.create( + uuid=uuid4(), checklist=self.checklist, template=self.template, lineitem=self.line_item2) + self.decision.save() + self.decision2.save() + self.data = dict() + self.peer_review_token = self.loginAndCreateSessionToken( + self.peer_review_user) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + self.admin_token = self.loginAndCreateSessionToken(self.admin_user) + + def initCLBody(self): + self.clbodydata['checkListName'] = ChecklistDefaultNames.HEAT_TEMPLATES + self.clbodydata['checkListTemplateUuid'] = str(self.template.uuid) + self.clbodydata[ + 'checkListAssociatedFiles'] = "[\"file0/f69f4ce7-51d5-409c-9d0e-ec6b1e79df28\", \"file1/f69f4ce7-51d5-409c-9d0e-ec6b1e79df28\", \"file2/f69f4ce7-51d5-409c-9d0e-ec6b1e79df28\"]" + + def loggerTestFailedOrSucceded(self, bool): + if bool: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test Succeeded") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + else: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug("Test failed") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + def testSetStateFullWorkFlow(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: Full positive work flow") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "checklist/@cl_uuid/state/" + self.get_checklist_url = self.urlPrefix + "checklist/@cl_uuid" + self.url_for_decision = self.urlPrefix + "checklist/decision/@decision_uuid" + + self.data['decline'] = "False" + self.data['description'] = "BLA BLA BLA" + datajson = json.dumps(self.data, ensure_ascii=False) + + logger.debug( + "**********************************************************************") + logger.debug("----- 1. Current state is " + + self.checklist.state + " -----") + logger.debug( + "**********************************************************************") + + logger.debug( + "----- 1.1 Wishing to move from pending state to automation state -----") + logger.debug( + "----- 1.2 Performing a request to move forward to the next state -----") + response = self.c.put(self.urlStr.replace("@cl_uuid", str(self.checklist.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('1.3 Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_200_OK) + ' response') + self.assertEqual(response.status_code, HTTP_200_OK) + + logger.debug( + "----- 2 Test engine Mock retrieved tests results, hence checklist state moved to review state. -----") + logger.debug( + "----- 3.1 changing decisions' review value to APPROVED -----") + decisions = ChecklistDecision.objects.filter(checklist=self.checklist) + for dec in decisions: + self.data['value'] = "approved" + datajson = json.dumps(self.data, ensure_ascii=False) + response = self.c.put(self.url_for_decision.replace("@decision_uuid", str(dec.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug( + "----- 3.2 Wishing to move from review state to peer_review state -----") + logger.debug( + "----- 3.3 Performing a request to move forward to the next state -----") + + response = self.c.put(self.urlStr.replace("@cl_uuid", str(self.checklist.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('3.4 you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_200_OK) + ' response') + self.assertEqual(response.status_code, HTTP_200_OK) + logger.debug( + "----- 4.1 changing the cl peer_reviews' decisions values to NA -----") + for dec in decisions: + dec.peer_review_value = CheckListDecisionValue.not_relevant.name # @UndefinedVariable + dec.save() + + logger.debug( + "----- 4.2 Wishing to move from peer_review state to approval state -----") + logger.debug( + "----- 4.3 Performing a request to move forward to the next state -----") + response = self.c.put(self.urlStr.replace("@cl_uuid", str(self.checklist.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.peer_review_token}) + logger.debug('4.4 Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_200_OK) + ' response') + self.assertEqual(response.status_code, HTTP_200_OK) + logger.debug( + "----- 5.1 Wishing to move from approval state to handoff state -----") + logger.debug( + "----- 5.2 Performing a request to move forward to the next state -----") + response = self.c.put(self.urlStr.replace("@cl_uuid", str(self.checklist.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + logger.debug('Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_200_OK) + ' response') + self.assertEqual(response.status_code, HTTP_200_OK) + logger.debug( + "----- 6.1 Wishing to move from handoff state to closed state -----") + logger.debug( + "----- 6.2 Performing a request to move forward to the last state -----") + response = self.c.put(self.urlStr.replace("@cl_uuid", str(self.checklist.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_200_OK) + ' response') + self.assertEqual(response.status_code, HTTP_200_OK) + self.loggerTestFailedOrSucceded(True) + + ''' + This test checks that the signal is sent and responds with 200OK. Also that the signal logic change the checklist state to automation + ''' + + def testClFromPendingToAutomationSignal(self): + + self.urlStr = self.urlPrefix + "checklist/@cl_uuid/state/" + self.get_checklist_url = self.urlPrefix + "checklist/@cl_uuid" + self.url_for_decision = self.urlPrefix + "checklist/decision/@decision_uuid" + + self.data['decline'] = "False" + self.data['description'] = "BLA BLA BLA" + datajson = json.dumps(self.data, ensure_ascii=False) + + cl = Checklist.objects.get(uuid=self.checklist.uuid) + cl.state = CheckListState.pending.name # @UndefinedVariable + cl.save() + res1 = self.c.put(self.urlStr.replace("@cl_uuid", str(self.checklist.uuid)), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + self.assertEqual(res1.status_code, HTTP_200_OK) diff --git a/django/engagementmanager/tests/test_set_eng_stage.py b/django/engagementmanager/tests/test_set_eng_stage.py new file mode 100755 index 0000000..f26b70b --- /dev/null +++ b/django/engagementmanager/tests/test_set_eng_stage.py @@ -0,0 +1,207 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from rest_framework.status import HTTP_202_ACCEPTED,\ + HTTP_401_UNAUTHORIZED +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import EngagementStage, Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class TestEngagementSetStage(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs']) + self.vendor = Vendor.objects.get(name='Amdocs') + self.service_provider = Vendor.objects.get(name=Constants.service_provider_company_name) + self.createDefaultRoles() + + # For negative tests + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + # Create users with role el (el+peer reviwer) + self.el_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'el user', self.el, True) + self.peer_reviewer = self.creator.createUser(self.service_provider, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + # Create a user with admin role + self.admin_user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), Constants.service_provider_admin_mail, + '55501000199', 'admin user', self.admin, True) + + self.engagement = self.creator.createEngagement('just-a-fake-uuid', 'Validation', None) + self.engagement.reviewer = self.el_user + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.engagement_team.add(self.el_user, self.user) + self.engagement.save() + + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) +# self.asInfrastructure = self.creator.createApplicationServiceInfrastructure(self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, self.vendor) +# self.vf.service_infrastructures.add(self.asInfrastructure) + + self.data = dict() + self.user_token = self.loginAndCreateSessionToken(self.user) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + self.admin_token = self.loginAndCreateSessionToken(self.admin_user) + + def loggerTestFailedOrSucceded(self, bool): + if bool: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test Succeeded") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + else: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug("Test failed") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + def testSetEngagementStageFullWorkFlowELUser(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: change from Intake to Active, using --EL-- user!") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + self.urlStr = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + "/stage/@stage" + self.get_engagement_url = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + datajson = json.dumps(self.data, ensure_ascii=False) + + logger.debug("**********************************************************************") + logger.debug("----- 1. Current stage is " + self.engagement.engagement_stage + " -----") + logger.debug("**********************************************************************") + + logger.debug("----- 1.1 Wishing to move from Intake stage to Active stage -----") + logger.debug("----- 1.2 Performing a request to move forward to the next stage -----") + response = self.c.put(self.urlStr.replace("@stage", EngagementStage.Active.name), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + response2 = self.c.get(self.get_engagement_url, {}, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + + # Check if the correct activity was created for stage change to Active + self.notifcation_url = self.urlPrefix + "engagement/" + str(self.engagement.uuid) + "/activities/" + response3 = self.c.get(self.notifcation_url, {}, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + received_notification = json.loads(response3.content)[0]['description'] + should_be = "Engagement stage is now Active for the following VF: ##vf_name##" + self.assertEqual(should_be, received_notification) + self.assertEqual(self.vf.name in json.loads(response3.content)[0]['metadata'], True) + logger.debug('1.3 Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_202_ACCEPTED) + ' response') + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + logger.debug("----- 2 Wishing to move from Active stage to Validated stage -----") + logger.debug("----- 2.1 Performing a request to move forward to the next stage -----") + response = self.c.put(self.urlStr.replace("@stage", EngagementStage.Validated.name), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('2.3 Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_202_ACCEPTED) + ' response') + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + logger.debug("----- 3.1 Wishing to move from Validated stage to Completed stage -----") + logger.debug("----- 3.2 Performing a request to move forward to the next stage -----") + response = self.c.put(self.urlStr.replace("@stage", EngagementStage.Completed.name), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.ELtoken}) + logger.debug('2.4 you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_202_ACCEPTED) + ' response') + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + self.loggerTestFailedOrSucceded(True) + + def testSetEngagementStageFullWorkFlowAdminUser(self): + + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: change from Intake to Active, using --ADMIN-- user!") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + "/stage/@stage" + self.get_engagement_url = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + datajson = json.dumps(self.data, ensure_ascii=False) + + logger.debug("**********************************************************************") + logger.debug("----- 1. Current stage is " + self.engagement.engagement_stage + " -----") + logger.debug("**********************************************************************") + + logger.debug("----- 1.1 Wishing to move from Intake stage to Active stage -----") + logger.debug("----- 1.2 Performing a request to move forward to the next stage -----") + response = self.c.put(self.urlStr.replace("@stage", EngagementStage.Active.name), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + logger.debug('1.3 Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_202_ACCEPTED) + ' response') + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + self.loggerTestFailedOrSucceded(False) + logger.debug("----- 2 Wishing to move from Active stage to Validated stage -----") + logger.debug("----- 2.1 Performing a request to move forward to the next stage -----") + response = self.c.put(self.urlStr.replace("@stage", EngagementStage.Validated.name), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + logger.debug('2.3 Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_202_ACCEPTED) + ' response') + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + logger.debug("----- 3 Wishing to move from Validated stage to Completed stage -----") + logger.debug("----- 3.1 Performing a request to move forward to the next stage -----") + response = self.c.put(self.urlStr.replace("@stage", EngagementStage.Completed.name), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.admin_token}) + logger.debug('2.4 you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_202_ACCEPTED) + ' response') + self.assertEqual(response.status_code, HTTP_202_ACCEPTED) + self.loggerTestFailedOrSucceded(True) + + def test_negative_set_eng_Stage(self): + + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: Negative test to change stage with un authorized user") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + self.urlStr = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + "/stage/@stage" + self.get_engagement_url = self.urlPrefix + "single-engagement/" + str(self.engagement.uuid) + datajson = json.dumps(self.data, ensure_ascii=False) + + logger.debug("**********************************************************************") + logger.debug("----- 1. Current stage is " + self.engagement.engagement_stage + " -----") + logger.debug("**********************************************************************") + + logger.debug("----- 1.1 Wishing to try move from Intake stage to Active stage AND FAIL! -----") + logger.debug("----- 1.2 Performing a request to move forward to the next stage -----") + response = self.c.put(self.urlStr.replace("@stage", EngagementStage.Active.name), datajson, + content_type='application/json', **{'HTTP_AUTHORIZATION': "token " + self.user_token}) + logger.debug('1.3 Please Notice, you got a ' + str(response.status_code) + + ' response, and was expecting a ' + str(HTTP_401_UNAUTHORIZED) + ' response') + self.assertEqual(response.status_code, HTTP_401_UNAUTHORIZED) + self.loggerTestFailedOrSucceded(True) diff --git a/django/engagementmanager/tests/test_update_password.py b/django/engagementmanager/tests/test_update_password.py new file mode 100755 index 0000000..08b25b2 --- /dev/null +++ b/django/engagementmanager/tests/test_update_password.py @@ -0,0 +1,99 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.models import Vendor +from engagementmanager.utils.constants import Constants + + +class TestUpdatePasswordTestCase(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs']) + self.createDefaultRoles() + + # Create a user with role el + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + + self.urlStr = self.urlPrefix + "users/pwd/" + self.data = dict() + self.token = self.loginAndCreateSessionToken(self.user) + + def initBody(self): + self.data['password'] = "Aa12345" + self.data['confirm_password'] = "Aa12345" + + def updatePwd(self, expectedStatus=200, httpMethod="PUT"): + self.accountData = json.dumps(self.data, ensure_ascii=False) + if (httpMethod == "PUT"): + response = self.c.put(self.urlStr, self.accountData, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + elif (httpMethod == "POST"): + response = self.c.post(self.urlStr, self.accountData, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code) + " Expecting " + str(expectedStatus)) + self.assertEqual(response.status_code, expectedStatus) + return response + + ### TESTS ### + def testUpdatePasswordPositive(self): + self.initBody() + print("testUpdatePasswordPositive") + self.updatePwd(200, "PUT") + + def testUpdatePasswordNegative(self): + self.initBody() + print("testUpdatePasswordNegative") + self.updatePwd(405, "POST") + + def testUpdatePasswordNegativePwdNotMatch(self): + self.initBody() + self.data['confirm_password'] = self.data['password'] + "extraletters" + print("testUpdatePasswordNegativePwdNotMatch") + self.updatePwd(400, "PUT") + + def testUpdatePasswordNegativeMissingPassword(self): + self.initBody() + self.data['confirm_password'] = None + print("testUpdatePasswordNegativePwdNotMatch") + self.updatePwd(400, "PUT") diff --git a/django/engagementmanager/tests/test_update_user_account.py b/django/engagementmanager/tests/test_update_user_account.py new file mode 100755 index 0000000..fd0becd --- /dev/null +++ b/django/engagementmanager/tests/test_update_user_account.py @@ -0,0 +1,119 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json + +from engagementmanager.models import Vendor, IceUserProfile +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants + + +class TestUpdateUserAccountTestCase(TestBaseEntity): + + def childSetup(self): + + self.createVendors([Constants.service_provider_company_name, 'Amdocs']) + + self.createDefaultRoles() + + # Create a user with role el + self.user = self.creator.createUser(Vendor.objects.get( + name=Constants.service_provider_company_name), self.randomGenerator("main-vendor-email"), + '55501000199', 'user', self.standard_user, True) + print('-----------------------------------------------------') + print('Created User:') + print('UUID: ' + str(self.user.uuid)) + print('Full Name: ' + self.user.full_name) + print('-----------------------------------------------------') + + self.urlStr = self.urlPrefix + "users/account/" + self.data = dict() + self.token = self.loginAndCreateSessionToken(self.user) + + def initBody(self): + self.data['company'] = Vendor.objects.get(name='Amdocs').name + self.data['full_name'] = "user" + self.data['email'] = self.randomGenerator("main-vendor-email") + self.data['phone_number'] = "12345" + self.data['password'] = "Aa12345" + self.data['confirm_password'] = "Aa12345" + + def updateAccount(self, expectedStatus=200, httpMethod="PUT"): + self.accountData = json.dumps(self.data, ensure_ascii=False) + if (httpMethod == "PUT"): + response = self.c.put(self.urlStr, self.accountData, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + elif (httpMethod == "POST"): + response = self.c.post(self.urlStr, self.accountData, content_type='application/json', + **{'HTTP_AUTHORIZATION': "token " + self.token}) + print('Got response : ' + str(response.status_code) + " Expecting 200") + self.assertEqual(response.status_code, expectedStatus) + return response + + ### TESTS ### + def testUpdateNegativeWrongHttpMethodAccount(self): + self.initBody() + print("Negative Test: Wrong HTTP Method --> Expecting status code 405") + self.updateAccount(405, "POST") + + def testUpdateNegativeDiffPasswords(self): + self.initBody() + print("Negative Test: password!=confirm_password --> Expecting status code 400") + self.data['confirm_password'] = "fakePassword" + self.updateAccount(400, "PUT") + + def testUpdatePositive(self): + self.initBody() + print("Positive Test: --> Expecting status code 200") + self.updateAccount(200, "PUT") + + def testUpdateUserProfileNotificationsSettings(self): + self.initBody() + + self.data['regular_email_updates'] = False + self.data['email_updates_daily_digest'] = True + self.data['email_updates_on_every_notification'] = False + + print("Positive Test: --> Expecting status code 200") + + self.updateAccount(200, "PUT") + + user = IceUserProfile.objects.get(uuid=self.user.uuid) + self.assertEqual(user.regular_email_updates, False) + self.assertEqual(user.email_updates_daily_digest, True) + self.assertEqual(user.email_updates_on_every_notification, False) diff --git a/django/engagementmanager/tests/test_vfc.py b/django/engagementmanager/tests/test_vfc.py new file mode 100755 index 0000000..e7f374a --- /dev/null +++ b/django/engagementmanager/tests/test_vfc.py @@ -0,0 +1,180 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_200_OK +from engagementmanager.models import Vendor +from engagementmanager.tests.test_base_entity import TestBaseEntity +from engagementmanager.utils.constants import Constants +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class VFCAPITestCase(TestBaseEntity): + + def childSetup(self): + self.createVendors([Constants.service_provider_company_name, 'Other']) + self.createDefaultRoles() + # Create a user with role el + self.service_provider = Vendor.objects.get(name=Constants.service_provider_company_name) + self.el_user = self.creator.createUser(self.service_provider, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + logger.debug('-----------------------------------------------------') + logger.debug('Created User:') + logger.debug('UUID: ' + str(self.el_user.uuid)) + logger.debug('Full Name: ' + self.el_user.full_name) + logger.debug('-----------------------------------------------------') + self.peer_reviewer = self.creator.createUser(self.service_provider, self.randomGenerator( + "main-vendor-email"), self.randomGenerator("randomNumber"), self.randomGenerator("randomString"), self.el, True) + logger.debug('-----------------------------------------------------') + logger.debug('Created Peer Reviewer:') + logger.debug('UUID: ' + str(self.peer_reviewer.uuid)) + logger.debug('Full Name: ' + self.peer_reviewer.full_name) + logger.debug('-----------------------------------------------------') + + # Create a user with role standard_user + self.vendor = Vendor.objects.get(name='Other') + self.user = self.creator.createUser(self.vendor, self.randomGenerator("email"), self.randomGenerator( + "randomNumber"), self.randomGenerator("randomString"), self.standard_user, True) + logger.debug('-----------------------------------------------------') + logger.debug('Created User:') + logger.debug('UUID: ' + str(self.user.uuid)) + logger.debug('Full Name: ' + self.user.full_name) + logger.debug('-----------------------------------------------------') + + # Create an Engagement with team + self.engagement = self.creator.createEngagement(self.randomGenerator( + "randomString"), self.randomGenerator("randomString"), None) + self.engagement.engagement_team.add(self.user, self.el_user, self.peer_reviewer) + self.engagement.peer_reviewer = self.peer_reviewer + self.engagement.reviewer = self.el_user + self.engagement.save() + logger.debug('-----------------------------------------------------') + logger.debug('Created Engagement:') + logger.debug('UUID: ' + str(self.engagement.uuid)) + logger.debug('-----------------------------------------------------') + + # Create a DT, DTSite, VF + self.deploymentTarget = self.creator.createDeploymentTarget( + self.randomGenerator("randomString"), self.randomGenerator("randomString")) + self.vf = self.creator.createVF(self.randomGenerator("randomString"), + self.engagement, self.deploymentTarget, False, self.vendor) + + logger.debug('-----------------------------------------------------') + logger.debug('Created VF:') + logger.debug('UUID: ' + str(self.vendor.uuid)) + logger.debug('-----------------------------------------------------') + + self.token = self.loginAndCreateSessionToken(self.user) + self.ELtoken = self.loginAndCreateSessionToken(self.el_user) + + def retrieveCurrentObjectsOfEngagementByFilter(self, method, detailOrObject, entity): + if method == 'filter': + list = entity.objects.filter(engagement=detailOrObject) + return list + elif method == 'get': + list = entity.objects.get(uuid=detailOrObject) + return list + + def loggerTestFailedOrSucceded(self, bool): + if bool: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test Succeeded") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + else: + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug("Test failed") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + + def testCreateDTSiteAddToVF(self): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: Create DTSite and add to VF") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + self.deploymentTargetSite = self.creator.createDeploymentTargetSite(self.randomGenerator("randomString")) + self.vf.deployment_target_sites.add(self.deploymentTargetSite) + sites = self.vf.deployment_target_sites.all() + num = 1 + for item in sites: + logger.debug(str(num) + ". " + item.name) + print("\n") + if (self.vf.deployment_target_sites.all().count() > 0): + self.loggerTestFailedOrSucceded(True) + else: + self.loggerTestFailedOrSucceded(False) + + def testDeleteVFC(self, expectedStatus=HTTP_204_NO_CONTENT): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: Delete VFC") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + vfc = self.creator.createVFC(self.randomGenerator("randomString"), self.randomGenerator( + "randomNumber"), self.vendor, self.vf, self.el_user) + urlStr = self.urlPrefix + 'vf/' + str(vfc.uuid) + '/vfcs/' + str(vfc.uuid) + if (vfc == None): + logger.error("vfc wasn't created successfully before the deletion attempt") + self.loggerTestFailedOrSucceded(False) + self.assertEqual(500, expectedStatus) + response = self.c.delete(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + logger.debug('Got response : ' + str(response.status_code)) + if (response.status_code == HTTP_204_NO_CONTENT): + self.loggerTestFailedOrSucceded(True) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, expectedStatus) + + def testGetVFC(self, expectedStatus=HTTP_200_OK): + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$") + logger.debug(" Test started: Get VFCs") + logger.debug("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n") + vfc = self.creator.createVFC(self.randomGenerator("randomString"), self.randomGenerator( + "randomNumber"), self.vendor, self.vf, self.el_user) + vfc2 = self.creator.createVFC(self.randomGenerator("randomString"), self.randomGenerator( + "randomNumber"), self.service_provider, self.vf, self.el_user) + urlStr = self.urlPrefix + 'vf/' + str(self.vf.uuid) + '/vfcs/' + if (vfc == None or vfc2 == None): + logger.error("The VFCs were not created successfully before the deletion attempt") + self.loggerTestFailedOrSucceded(False) + self.assertEqual(500, expectedStatus) + response = self.c.get(urlStr, **{'HTTP_AUTHORIZATION': "token " + self.token}) + logger.debug('Got response : ' + str(response.status_code)) + logger.debug("VFCs found in the VF(through the GET request):") + logger.debug(str(response.content)) + if (response.status_code == HTTP_200_OK): + self.loggerTestFailedOrSucceded(True) + else: + self.loggerTestFailedOrSucceded(False) + self.assertEqual(response.status_code, expectedStatus) diff --git a/django/engagementmanager/tests/vvpEntitiesCreator.py b/django/engagementmanager/tests/vvpEntitiesCreator.py new file mode 100755 index 0000000..0ba619e --- /dev/null +++ b/django/engagementmanager/tests/vvpEntitiesCreator.py @@ -0,0 +1,290 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from uuid import uuid4 +from django.utils import timezone +import string +import random +from engagementmanager.service.logging_service import LoggingServiceFactory +from engagementmanager.utils.authentication import JWTAuthentication +from engagementmanager.models import Vendor, IceUserProfile, Role, Engagement, DeploymentTarget, ApplicationServiceInfrastructure, VF,\ + NextStep, ChecklistTemplate, DeploymentTargetSite, VFC, Checklist, ChecklistSection, ChecklistLineItem,\ + CustomUser +from engagementmanager.utils.constants import Constants + +logger = LoggingServiceFactory.get_logger() + + +class VvpEntitiesCreator: + + def __init__(self): + pass + + def createUserTemplate(self, company, email, full_name, role, is_service_provider_contact, ssh_key=None, ): + return { + 'company': company, + 'email': email, + 'phone_number': '555019900', + 'full_name': full_name, + 'role': role, + 'create_time': timezone.now(), + 'is_service_provider_contact': is_service_provider_contact, + 'ssh_public_key': ssh_key, + } + + def createEngagementTemplate(self, engagement_type, engagement_team): + return { + # 'engagement_type' : engagement_type, + # 'members' : engagement_team, + # 'start_date' : timezone.now(), + 'progress': 0 + } + + def createVendor(self, vendorName): + ven = Vendor.objects.filter(name=vendorName) + if (not ven.exists()): + vendor = Vendor.objects.create(name=vendorName, public=True) + else: + vendor = Vendor.objects.get(name=vendorName) + return vendor.uuid, vendor + + def createDeploymentTarget(self, name, version): + deployment = DeploymentTarget.objects.create( + name=name, version=version) + return deployment + + def createDeploymentTargetSite(self, name): + dtsite = DeploymentTargetSite.objects.create(name=name) + return dtsite + + def createApplicationServiceInfrastructure(self, name): + asinfrastructure = ApplicationServiceInfrastructure.objects.create( + name=name) + return asinfrastructure + + def getOrCreateIfNotExist(self, entity, getCriteria, creationFields): + obj = None + try: + logger.debug("about to look for object: " + str(getCriteria)) + obj = entity.objects.get(**getCriteria) + logger.debug('found object') + except entity.DoesNotExist: + logger.error('not found. Trying to create...') + obj = entity.objects.create(**creationFields) + return obj + + def createAndGetDefaultRoles(self): + admin = self.getOrCreateIfNotExist( + Role, {'name': 'admin'}, {'name': 'admin'}) + el = self.getOrCreateIfNotExist(Role, {'name': 'el'}, {'name': 'el'}) + standard_user = self.getOrCreateIfNotExist(Role, {'name': 'standard_user'}, { + 'name': 'standard_user'}) + return admin, el, standard_user + + def createUser(self, company, email, phone, fullName, role, is_active=False, ssh_key=None, activation_token_create_time=timezone.now()): + try: + user, is_user_created = CustomUser.objects.get_or_create(username=email, defaults={'email': email, 'password': '12345678', 'activation_token': uuid4( + ), 'activation_token_create_time': timezone.now(), 'last_login': timezone.now(), 'is_active': is_active}) + user_profile, is_profile_created = IceUserProfile.objects.update_or_create( + email=email, defaults=self.createUserTemplate(company, email, fullName, role, False, ssh_key)) + except Exception as e: + logger.error("VvpEntitiesCreator - createUser - error:") + logger.error(e) + return None + return user_profile + + def createEngagement(self, uuid, engagement_type, engagement_team): + return self.getOrCreateIfNotExist(Engagement, {'uuid': uuid}, self.createEngagementTemplate(engagement_type, engagement_team)) + + def createVF(self, name, engagement, deployment, is_service_provider_internal, vendor, **kwargs): + vf = VF.objects.create(name=name, engagement=engagement, + deployment_target=deployment, + is_service_provider_internal=is_service_provider_internal, + vendor=vendor, + target_lab_entry_date=timezone.now(), **kwargs) + return vf + + def createNextStep(self, uuid, createFields): + return self.getOrCreateIfNotExist(NextStep, {'uuid': uuid}, createFields) + + def createDefaultCheckListTemplate(self): + checklist_templates = [ + { + 'name': 'Heat', + 'category': 'first category', + 'version': 1, + 'sections': [ + { + 'name': 'Parameter Specification', + 'weight': 1, + 'description': 'section description', + 'validation_instructions': 'valid instructions', + 'lineitems': [ + { + 'name': 'Parameters', + 'weight': 1, + 'description': 'Numeric parameters should include range and/or allowed values.', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'auto', + }, + { + 'name': 'String parameters', + 'weight': 1, + 'description': 'Numeric parameters should include range and/or allowed values.', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'auto', + }, + { + 'name': 'Numeric parameters', + 'weight': 1, + 'description': 'Numeric parameters should include range and/or allowed values.', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'auto', + } + ] + }, + { + 'name': 'External References', + 'weight': 1, + 'description': 'section descripyion', + 'validation_instructions': 'valid instructions', + 'lineitems': [ + { + 'name': 'Normal references', + 'weight': 1, + 'description': 'Numeric parameters should include range and/or allowed values.', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'manual', + }, + { + 'name': 'VF image', + 'weight': 1, + 'description': 'Numeric parameters should include range and/or allowed values.', + 'validation_instructions': 'Here are some useful tips for how to validate this item in the most awesome way:<br><br><ul><li>Here is my awesome tip 1</li><li>Here is my awesome tip 2</li><li>Here is my awesome tip 3</li></ul>', + 'line_type': 'auto', + } + ] + + } + ] + } + ] + + for template in checklist_templates: + created_template = ChecklistTemplate.objects.get_or_create(name=template['name'], defaults={ + 'category': template['category'], + 'version': template['version'], + 'create_time': timezone.now() + }) + created_template = ChecklistTemplate.objects.get( + name=template['name']) + for section in template['sections']: + created_section = ChecklistSection.objects.get_or_create( + name=section['name'], + template_id=created_template.uuid, defaults={ + 'weight': section['weight'], + 'description': section['description'], + 'validation_instructions': section['validation_instructions'] + + }) + created_section = ChecklistSection.objects.get( + name=section['name'], template_id=created_template.uuid) + for lineitem in section['lineitems']: + created_lineitem = ChecklistLineItem.objects.get_or_create( + name=lineitem['name'], + template_id=created_template.uuid, + defaults={ + 'weight': lineitem['weight'], + 'description': lineitem['description'], + 'validation_instructions': lineitem['validation_instructions'], + 'line_type': lineitem['line_type'], + 'section_id': created_section.uuid, + }) + + self.defaultCheklistTemplate = ChecklistTemplate.objects.get( + name="Heat") + + return self.defaultCheklistTemplate + + def createCheckList(self, name, state, validation_cycle, associated_files, engagement, template, creator, owner): + if (associated_files == None): + associated_files = '{}' + return self.getOrCreateIfNotExist(Checklist, {'name': name}, { + 'state': state, + 'name': name, + 'validation_cycle': 1, + 'associated_files': associated_files, + 'engagement': engagement, + 'template': template, + 'creator': creator, + 'owner': owner + }) + + def createVFC(self, name, ext_ref, company, vf, creator): + obj = None + try: + obj = VFC.objects.get(name=name) + except VFC.DoesNotExist: + return VFC.objects.create(name=name, external_ref_id=ext_ref, company=company, creator=creator, vf=vf) + return obj + + def randomGenerator(self, typeOfValue, numberOfDigits=0): + lettersAndNumbers = string.ascii_letters + string.digits + if typeOfValue == 'email': + myEmail = ''.join(random.choice(lettersAndNumbers) for _ in range(4)) + "@" + \ + ''.join(random.choice(string.ascii_uppercase) for _ in range(4)) + ".com" + return myEmail + elif typeOfValue == 'main-vendor-email': + myEmail = ''.join(random.choice(lettersAndNumbers) for _ in range(4)) + "@" + \ + Constants.service_provider_mail_domain[0] + return myEmail + elif typeOfValue == 'randomNumber': + randomNumber = ''.join("%s" % random.randint(0, 9) for _ in range(0, (numberOfDigits + 1))) + return randomNumber + elif typeOfValue == 'randomString': + randomString = "".join(random.sample(lettersAndNumbers, 5)) + return randomString + else: + logger.debug("Error on randonGenerator - given bad value.") + exit + + def loginAndCreateSessionToken(self, user): + jwt_service = JWTAuthentication() + token = jwt_service.create_token(user.user) + logger.debug("token " + token) + return token diff --git a/django/engagementmanager/urls.py b/django/engagementmanager/urls.py new file mode 100755 index 0000000..9cc5be3 --- /dev/null +++ b/django/engagementmanager/urls.py @@ -0,0 +1,227 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.conf.urls import url + +from engagementmanager.rest import checklist_audit_log +from engagementmanager.rest import user, activation, activity, vf, invite, feedback, nextsteps, engagement, \ + login, signup, notification, checklist, deployment_target_site, vendor, data_loader, checklist_decision, \ + vfc, checklist_set_state, deployment_target, ecomp, validation_details +from engagementmanager.rest.cms.pages import Pages, PageById, PageSearch +from engagementmanager.rest.cms.posts import Posts +from engagementmanager.rest.engagement import EngagementProgressBar, ChangeTargetLabEntryDate, EngagementOps, \ + EngagementReviewer, EngagementPeerReviewer, ArchiveEngagement, SwitchEngagementReviewers +from engagementmanager.rest.user import User +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +# Our UUIDs are always uuid4; a 36-character string of lowercase hexadecimal +# and '-' characters. +re_uuid = r'[a-f0-9-]{36}' +# UUIDs in tokens are the same as above without '-', so 32 lowercase +# hexadecimal characters. +re_token = r'[a-f0-9]{32}' +# Parameters like 'stage' correspond to Enums, so have the same rules as Python +# identifiers: upper and lower case, numbers, and underscore. +re_enum = r'[a-zA-Z0-9_\.-]+' + +re_token_reset_password = r'[a-zA-Z0-9-\._]+' + + +urlpatterns = [ + url(r'^users/engagementleads/?$', user.EngagementLeads.as_view()), + url(r'^users/ssh/?$', user.SetSsh.as_view()), + url(r'^users/account/?$', user.User.as_view()), + url(r'^users/account/rgwa/?$', user.RGWAAccessKey.as_view()), + url(r'^users/pwd/reset-instructions/?$', + user.SendResetPasswordInstructionMail.as_view()), + url(r'^users/pwd/?$', user.UpdatePassword.as_view()), + url(r'^users/?$', User.as_view()), + + # User Activation + url(r'^users/activation-mail/(?P<user_uuid>%s)$' % re_uuid, + activation.ResendActivationMail.as_view()), + url(r'^users/activate/(?P<uu_id>%s)/(?P<token>%s)$' % + (re_uuid, re_token), activation.ActivateUser.as_view()), + + # Engagements API + url(r'^single-engagement/(?P<eng_uuid>%s)/stage/(?P<stage>%s)$' % + (re_uuid, re_enum), engagement.SingleEngByUser.as_view()), + url(r'^single-engagement/(?P<eng_uuid>%s)$' % + re_uuid, engagement.SingleEngByUser.as_view()), + url(r'^engagements/user/nextsteps/?$', nextsteps.UserNextSteps.as_view()), + url(r'^engagements/starred_eng/?$', + engagement.StarredEngagements.as_view()), + url(r'^engagements/recent_eng/?$', + engagement.GetRecentEngagements.as_view()), + url(r'^engagements/engagement-team/?$', + engagement.EngagementTeamUsers.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/status/?$' % + re_uuid, engagement.Status.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/nextsteps/?$' % + re_uuid, nextsteps.NextSteps.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/nextsteps/order_next_steps$' % + re_uuid, nextsteps.OrderNextSteps.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/nextsteps/(?P<eng_stage>%s)/?$' % (re_uuid, re_enum), + nextsteps.NextSteps.as_view()), # Set Next Step State + # Set Progress bar for Engagement + url(r'^engagements/(?P<eng_uuid>%s)/progress/?$' % + re_uuid, EngagementProgressBar.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/target_date/?$' % + re_uuid, EngagementProgressBar.as_view()), # Set Target Date + # Set Target Lab Entry Date + url(r'^engagements/(?P<eng_uuid>%s)/target_lab_date/?$' % + re_uuid, ChangeTargetLabEntryDate.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/archive/?$' % + re_uuid, ArchiveEngagement.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/reviewer/?$' % + re_uuid, EngagementReviewer.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/peerreviewer/?$' % + re_uuid, EngagementPeerReviewer.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/switch-reviewers/?$' % + re_uuid, SwitchEngagementReviewers.as_view()), + url(r'^engagements/(?P<eng_uuid>%s)/$' % + re_uuid, EngagementOps.as_view()), # Used by delete engagement + url(r'^engagement/expanded/?$', engagement.ExpandedEngByUser.as_view()), + url(r'^engagement/export/', engagement.ExportEngagements.as_view()), + url(r'^engagement/?$', engagement.GetEngByUser.as_view()), + # Activities - pull top X objects + url(r'^engagement/(?P<eng_uuid>%s)/activities/?$' % + re_uuid, activity.PullActivities.as_view()), + + # DeploymentTarget(version) + url(r'^engagement/(?P<engagement_uuid>%s)/deployment-targets/(?P<dt_uuid>%s)$' + % (re_uuid, re_uuid), + deployment_target.DeploymentTargetRESTMethods.as_view()), + url(r'^deployment-targets/?$', + deployment_target.DeploymentTargetRESTMethods.as_view()), + + # ECOMP + url(r'^engagement/(?P<engagement_uuid>%s)/ecomp-releases/(?P<ecomp_uuid>%s)$' % (re_uuid, re_uuid), + ecomp.ECOMPReleaseRESTMethods.as_view()), + url(r'^ecomp-releases/?$', ecomp.ECOMPReleaseRESTMethods.as_view()), + # VFVERSION + url(r'^vf/(?P<vf_uuid>%s)/vf-version/$' % re_uuid, vf.VF.as_view()), + # DeploymentTargetSite%s + url(r'^vf/(?P<vf_uuid>%s)/validation-details/$' % + re_uuid, validation_details.UpdateValidationDetails.as_view()), + url(r'^vf/(?P<vf_uuid>%s)/dtsites/$' % + re_uuid, deployment_target_site.DTSites.as_view()), + url(r'^vf/(?P<vf_uuid>%s)/dtsites/(?P<dts_uuid>%s)$' % + (re_uuid, re_uuid), deployment_target_site.DTSites.as_view()), + url(r'^dtsites/?$', deployment_target_site.DTSites.as_view()), + + # Vendor + url(r'^vendors/?$', vendor.VendorREST.as_view()), + url(r'^vendors/(?P<uuid>%s)$' % re_uuid, vendor.VendorREST.as_view()), + + url(r'^vfcs/?$', vfc.VFCRest.as_view()), + url(r'^vf/(?P<vf_uuid>%s)/vfcs/$' % re_uuid, vfc.VFCRest.as_view()), + url(r'^vf/(?P<vf_uuid>%s)/vfcs/(?P<vfc_uuid>%s)?$' % + (re_uuid, re_uuid), vfc.VFCRest.as_view()), + + # Next Steps + url(r'^nextsteps/(?P<ns_uuid>%s)/engagement/(?P<eng_uuid>%s)?$' % (re_uuid, re_uuid), + nextsteps.EditNextSteps.as_view()), # Set State for a next step + url(r'^nextsteps/(?P<ns_uuid>%s)/(?P<attr>state)/?$' % + re_uuid, nextsteps.NextSteps.as_view()), # Set State for a next step + url(r'^nextsteps/(?P<ns_uuid>%s)$' % + re_uuid, nextsteps.EditNextSteps.as_view()), + + # Login + Signup: + url(r'^login(?P<param>%s)?$' % + re_token_reset_password, login.Login.as_view()), + url(r'^signup/?$', signup.SignUp.as_view()), + + # User Actions + url(r'^vf/?$', vf.VF.as_view()), + url(r'^add-contact/?$', invite.InviteContact.as_view()), + url(r'^invite-team-members/?$', invite.InviteTeamMember.as_view()), + url(r'^add-feedback/?$', feedback.Feedback.as_view()), + + # Notifications - set notifications for specific user to is_read = True + url(r'^notifications/reset/?$', notification.NotificationOps.as_view()), + url(r'^notifications/num/?$', notification.PullNotifCount4User.as_view()), + + # Notifications - pull unread objects + url(r'^notifications/(?P<user_uuid>%s)/(?P<offset>\d+)/(?P<limit>\d+)$' % + re_uuid, notification.NotificationOps.as_view()), + # Notifications - delete specific notification for a user + url(r'^notifications/(?P<notif_uuid>%s)$' % + re_uuid, notification.NotificationOps.as_view()), + + # Initialize the engagement leads + url(r'^load-engagement-leads/?$', + data_loader.EngLeadsDataLoader.as_view()), + # Initialize companies + url(r'^load-companies/?$', data_loader.CompaniesDataLoader.as_view()), + + # get/add CLAuditLogs + url(r'^checklist/decision/(?P<decision_uuid>%s)/auditlog/$' % + re_uuid, checklist_audit_log.DecisionAuditLog.as_view()), + url(r'^checklist/(?P<checklistUuid>%s)/auditlog/$' % + re_uuid, checklist_audit_log.ChecklistAuditLog.as_view()), + + # get/set CLDecision + url(r'^checklist/decision/(?P<decision_uuid>%s)$' % + re_uuid, checklist_decision.ClDecision.as_view()), + # get/set CLDecision + url(r'^checklist/(?P<checklistUuid>%s)/state/$' % + re_uuid, checklist_set_state.ChecklistState.as_view()), + + url(r'^checklist/template/$', checklist.CheckListTemplates.as_view()), + url(r'^checklist/templates/$', checklist.CheckListTemplates.as_view()), + url(r'^checklist/template/(?P<templateUuid>%s)$' % + re_uuid, checklist.CheckListTemplates.as_view()), + + # get Checklist (returns files and all templates) + url(r'^engagement/(?P<eng_uuid>%s)/checklist/(?P<checklistUuid>%s)/nextstep/$' % (re_uuid, re_uuid), + nextsteps.ChecklistNextStep.as_view()), + url(r'^engagement/(?P<eng_uuid>%s)/checklist/new/$' % + re_uuid, checklist.NewCheckList.as_view()), + url(r'^checklist/(?P<checklistUuid>%s)$' % + re_uuid, checklist.ExistingCheckList.as_view()), + url(r'^checklist/$', checklist.ExistingCheckList.as_view()), + + url(r'^cms/posts/$', Posts.as_view()), + url(r'^cms/pages/$', Pages.as_view()), + url(r'^cms/pages/search/?$', PageSearch.as_view()), + url(r'^cms/pages/(?P<id>\d+)/$', PageById.as_view()), +] diff --git a/django/engagementmanager/utils/__init__.py b/django/engagementmanager/utils/__init__.py new file mode 100755 index 0000000..371b694 --- /dev/null +++ b/django/engagementmanager/utils/__init__.py @@ -0,0 +1,65 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. + + +def dict_path_get(dicttree, path, default=None): + """Use a /-separated path to query a structure of nested dicts. + + Note: If the path does not exist, this will return None instead of + raising an exception. + + >>> nested = { + ... 'a': { + ... 'b': { + ... 'c': 'foo' + ... } + ... } + ... } + ... + >>> dict_path_get(nested, 'a/b/c') + 'foo' + + """ + d = dicttree + try: + for k in path.split('/'): + d = d[k] + except KeyError: + d = default + return d diff --git a/django/engagementmanager/utils/activities_data.py b/django/engagementmanager/utils/activities_data.py new file mode 100755 index 0000000..24275d6 --- /dev/null +++ b/django/engagementmanager/utils/activities_data.py @@ -0,0 +1,116 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from engagementmanager.utils.constants import ActivityType + + +class ActivityData: + def __init__(self, engagement, activity_type, owner=None): + self.engagement = engagement + self.description = '' + self.metadata = {} + self.activity_type = activity_type + self.is_notification = False + self.owner = owner + self.multiple_users_as_owners = False + self.user = None + + +class UserJoinedEngagementActivityData(ActivityData): + def __init__(self, vf, users_list, engagement, owner=None): + super(UserJoinedEngagementActivityData, self).__init__(engagement, ActivityType.user_joined_eng, owner) + self.vf = vf + self.users_list = users_list + + +class VFProvisioningActivityData(ActivityData): + def __init__(self, vf, users_list, engagement, description="There was an error provisioning the VF", owner=None): + super(VFProvisioningActivityData, self).__init__(engagement, ActivityType.vf_provisioning_event, owner) + self.vf = vf + self.description = description + self.users_list = users_list + + +class TestFinishedActivityData(ActivityData): + def __init__(self, users_list, engagement, description="There was an error in Test" + " Finished signal from Jenkins", owner=None): + super(TestFinishedActivityData, self).__init__(engagement, ActivityType.test_finished_event, owner) + self.description = description + self.users_list = users_list + + +class ChangeEngagementStageActivityData(ActivityData): + def __init__(self, vf, stage, engagement, owner=None): + super(ChangeEngagementStageActivityData, self).__init__(engagement, ActivityType.change_engagement_stage, owner) + self.vf = vf + self.stage = stage + + +class AddNextStepsActivityData(ActivityData): + def __init__(self, vf, user, engagement, owner=None): + super(AddNextStepsActivityData, self).__init__(engagement, ActivityType.add_next_steps, owner) + self.vf = vf + self.user = user + + +class NoticeEmptyEngagementData(ActivityData): + def __init__(self, vf_name, max_empty_time, git_repo_url, delta_days_from_creation, engagement, owner=None): + super(NoticeEmptyEngagementData, self).__init__(engagement, ActivityType.notice_empty_engagement, owner) + self.max_empty_time = max_empty_time + self.vf_name = vf_name + self.git_repo_url = git_repo_url + self.delta_days_from_creation = delta_days_from_creation + + +class UpdateNextStepsActivityData(ActivityData): + def __init__(self, update_type, user, engagement, owner=None): + super(UpdateNextStepsActivityData, self).__init__(engagement, ActivityType.update_next_steps, owner) + self.update_type = update_type + self.user = user + + +class DeleteNextStepsActivityData(ActivityData): + def __init__(self, user, engagement, owner=None): + super(DeleteNextStepsActivityData, self).__init__(engagement, ActivityType.delete_next_steps, owner) + self.user = user + + +class SSHKeyAddedActivityData(ActivityData): + def __init__(self, action, engagement, owner=None): + super(SSHKeyAddedActivityData, self).__init__(engagement, ActivityType.ssh_key_added, owner) + self.action = action diff --git a/django/engagementmanager/utils/authentication.py b/django/engagementmanager/utils/authentication.py new file mode 100755 index 0000000..6a857d6 --- /dev/null +++ b/django/engagementmanager/utils/authentication.py @@ -0,0 +1,91 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from itsdangerous import URLSafeTimedSerializer +from rest_framework_jwt.settings import api_settings +from rest_framework_jwt.utils import jwt_decode_handler +from engagementmanager.models import IceUserProfile +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def ice_jwt_decode_handler(token): + decoded_dict = jwt_decode_handler(token) + email = decoded_dict.get('email', None) + user = IceUserProfile.objects.get(email=email) + request_data_mgr.clear_old_request_data() + request_data_mgr.set_user(user) + return decoded_dict + + +class JWTAuthentication(object): + """ + Simple token based authentication. + Clients should authenticate by passing the token key in the "Authorization" HTTP header, prepended with the string "Token ". + For example: Authorization: Token 401f7ac837da42b97f613d789819ff93537bee6a + """ + + def create_token(self, user_data): + jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER + jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER + + payload = jwt_payload_handler(user_data) + token = jwt_encode_handler(payload) + return token + + def create_reset_password_token(self, user_data): + """ + Create token for reset password flow. + """ + encryptor = URLSafeTimedSerializer(api_settings.JWT_SECRET_KEY) + return encryptor.dumps(user_data.email, salt=api_settings.JWT_SECRET_KEY) + + def decode_reset_password_token(self, token): + """ + Decoded the token created at reset password flow and return what was encrypted. + """ + decryptor = URLSafeTimedSerializer(api_settings.JWT_SECRET_KEY) + email = decryptor.loads( + token, + salt=api_settings.JWT_SECRET_KEY, + max_age=3600 + ) + + return email diff --git a/django/engagementmanager/utils/choice_enum.py b/django/engagementmanager/utils/choice_enum.py new file mode 100755 index 0000000..ef19de2 --- /dev/null +++ b/django/engagementmanager/utils/choice_enum.py @@ -0,0 +1,56 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from enum import Enum + + +class ChoiceEnum(Enum): + """An Enumeration with an added choices() method useful in Django""" + + @classmethod + def choices(cls): + """Return this Enum's values in a format suitable for use as Django Field.choices param. + + https://docs.python.org/3/library/enum.html + https://docs.djangoproject.com/en/1.10/ref/models/fields/#choices + + """ + # FIXME it might be more useful in some situations to return (x.value, x.name), but we do + # this way is for compatibility with older versions of this code. Changing would require a + # data migration.` + return [(x.name, x.name) for x in cls] diff --git a/django/engagementmanager/utils/constants.py b/django/engagementmanager/utils/constants.py new file mode 100755 index 0000000..c5b1ae9 --- /dev/null +++ b/django/engagementmanager/utils/constants.py @@ -0,0 +1,211 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.conf import settings +from enum import Enum +from engagementmanager.utils.choice_enum import ChoiceEnum + + +class Roles(Enum): + standard_user = 1 + el = 2 + admin = 3 + admin_ro = 4 + + +class Constants(object): + service_provider_company = None + role_el = None + role_standard_user = None + role_admin = None + role_admin_ro = None + service_provider_company_name = "ExampleServiceProvider" + service_provider_mail_domain = ["example.com"] + service_provider_admin_mail = "admin@example.com" + service_provider_admin_ro_mail = "admin_ro@example.com" + ice_base_ctx = "/vvp/v1/engmgr/" + rgwa_base_url ='http://localhost:8123/admin' + default_vfc_version = "1.0.0" + dbConnectionStr = "dbname='icedb' user='iceuser' host='localhost' password='Aa123456' port='5433'" + dashboard_href = "<A href=" + \ + str(settings.DOMAIN) + "/#/dashboard/" + ">Dashboard</A>" + prodDomain = 'https://www.vvp.example.com' + invite_template_dir = "emails/invite/" + activate_template_dir = "emails/activate/" + notification_template_dir = "emails/notification/" + reset_pwd_template_dir = "emails/reset_pwd/" + activation_prefix = "/#/activate/" + program_name = "VVP" + + +class TemplatesConstants(object): + logo_url = "https://www.d2ice.att.io/styles/images/d2sandbox_logos-150x30.png" + contact_mail = "d2ice@att.com" + context = {"service_provider": Constants.service_provider_company_name, + "program_name": Constants.program_name, + "logo_url": logo_url, + "contact_mail": contact_mail, + } + + +''' +In order to get Enum Value as String use: EngagementType.Validation.name +''' +class EngagementModelValidationDate: + HEAT_VALIDATED = "heat_validated_time" + IMAGE_SCAN = "image_scan_time" + AIC_INSTANTIATION = "aic_instantiation_time" + ASDC_ONBOARDING = "asdc_onboarding_time" + + +class JenkinsBuildParametersNames: + CHECKLIST_UUID = "checklist_uuid" + GIT_REPO_URL = "git_repo_url" + + +class MockJenkinsBuildLog: + TEXT = "from server: Started by user admin \n \ + Building in workspace /var/jenkins_home/workspace/{vf_name}_{eng_man_id} \n \ + [{vf_name}_{eng_man_id}] $ /bin/sh /tmp/jenkins{random_id}.sh \n \ + Cloning into '/var/jenkins_home/workspace/{vf_name}_{eng_man_id}/VF'" + + +class ChecklistDefaultNames: + HEAT_TEMPLATES = "Heat Templates" + IMAGE_VALIDATION = "Image Validation" + AIC_INSTANTIATION = "AIC Instantiation" + ASDC_ONBOARDING = "ASDC Onboarding" + VALIDATION_DATE_ARRAY = { + HEAT_TEMPLATES: EngagementModelValidationDate.HEAT_VALIDATED, + IMAGE_VALIDATION: EngagementModelValidationDate.IMAGE_SCAN, + AIC_INSTANTIATION: EngagementModelValidationDate.AIC_INSTANTIATION, + ASDC_ONBOARDING: EngagementModelValidationDate.ASDC_ONBOARDING + } + + +class EngagementType(Enum): + Validation = 1 + Other = 2 + + +class EngagementStage(ChoiceEnum): + Intake = 1, + Active = 2, + Validated = 3, + Completed = 4, + Archived = 5 + + +class NextStepState(ChoiceEnum): + Incomplete = 1, + Completed = 2 + + +class RGWApermission: + READ = 'READ', + WRITE = 'WRITE' + + +class NextStepType(ChoiceEnum): + set_ssh = 1, + trial_agreements = 2, + add_contact_person = 3, + submit_vf_package = 4, + el_handoff = 5, + user_defined = 6 + + +class ExceptionType(Enum): + TSS = 1 + STAT = 2 + + +# NOTE: For each added activity that you wish to send notification mail, +# add an "if" in activity_log::getSubjectAndDescByActivityType +class ActivityType(ChoiceEnum): + user_joined_eng = 1 + ssh_key_added = 2 + eng_validation_request = 3 + update_next_steps = 4 + vfc = 5 + change_checklist_state = 6 + vf_provisioning_event = 7 + test_finished_event = 8 + change_engagement_stage = 9 + add_next_steps = 10 + delete_next_steps = 11 + notice_empty_engagement = 12 + + +class CheckListLineType(ChoiceEnum): + auto = 1, + manual = 2 + + +class CheckListState(ChoiceEnum): + automation = 1, + review = 2, + peer_review = 3, + approval = 4, + handoff = 5, + closed = 6, + archive = 7, + pending = 8 + + +class CheckListCategory(ChoiceEnum): + overall = 1, + heat = 2, + glance = 3 + instantiation = 4 + asdc = 5 + + +class CheckListDecisionValue(ChoiceEnum): + approved = 1, + denied = 2, + not_relevant = 3, + na = 4 + + +class RecentEngagementActionType(ChoiceEnum): + JOINED_TO_ENGAGEMENT = 1, + NEXT_STEP_ASSIGNED = 2, + GOT_OWNERSHIP_OVER_ENGAGEMENT = 3, + NAVIGATED_INTO_ENGAGEMENT = 4, + NEW_VF_CREATED = 5, diff --git a/django/engagementmanager/utils/cryptography.py b/django/engagementmanager/utils/cryptography.py new file mode 100755 index 0000000..723efa0 --- /dev/null +++ b/django/engagementmanager/utils/cryptography.py @@ -0,0 +1,61 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from itsdangerous import URLSafeTimedSerializer +from rest_framework_jwt.settings import api_settings +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class CryptographyText(object): + + @staticmethod + def encrypt(text): + encryptor = URLSafeTimedSerializer(api_settings.JWT_SECRET_KEY) + return encryptor.dumps(text, salt=api_settings.JWT_SECRET_KEY) + + @staticmethod + def decrypt(encoded_text): + decryptor = URLSafeTimedSerializer(api_settings.JWT_SECRET_KEY) + text = decryptor.loads( + encoded_text, + salt=api_settings.JWT_SECRET_KEY, + ) + + return text diff --git a/django/engagementmanager/utils/dates.py b/django/engagementmanager/utils/dates.py new file mode 100755 index 0000000..db1d8fe --- /dev/null +++ b/django/engagementmanager/utils/dates.py @@ -0,0 +1,51 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from datetime import datetime + + +def parse_date(date_string, convention=None): + result = None + + if convention is None: + convention = '%Y-%m-%dT%H:%M:%S.%fZ' + + if date_string is not None: + result = datetime.strptime(str(date_string), convention) + + return result diff --git a/django/engagementmanager/utils/exception_handler.py b/django/engagementmanager/utils/exception_handler.py new file mode 100755 index 0000000..b1b46ee --- /dev/null +++ b/django/engagementmanager/utils/exception_handler.py @@ -0,0 +1,73 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import traceback +from rest_framework.response import Response +from rest_framework.views import exception_handler +from engagementmanager.utils.exception_message_factory import ExceptionMessageFactory +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def ice_exception_handler(exc, context): + """ + our own exception handler so we will catch every exception occurred in rest and print it's stack into log + :param exc: The exception + :param context: The context which the exception occurred in. + """ + response = exception_handler(exc, context) + + if exc is not None: + message_factory = ExceptionMessageFactory() + exception_msg_obj = message_factory.get_exception_message(exc) + data = {'detail': exception_msg_obj['msg']} + + if exception_msg_obj['include_exception']: + data['detail'] += str(exc) + if 'include_additional_exc_str' in exception_msg_obj and exception_msg_obj['include_additional_exc_str']: + data['exception_message'] = str(exc) + + response = Response(data, status=exception_msg_obj['status']) + + logger.error("General exception occurred in rest framework: %s", exc) + logger.debug("*******************************************************************************************") + logger.debug(traceback.format_exc()) + logger.debug("*******************************************************************************************") + + return response diff --git a/django/engagementmanager/utils/exception_message_factory.py b/django/engagementmanager/utils/exception_message_factory.py new file mode 100755 index 0000000..6ea96f4 --- /dev/null +++ b/django/engagementmanager/utils/exception_message_factory.py @@ -0,0 +1,92 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.core.exceptions import ObjectDoesNotExist +from django.core.management.base import CommandError +from engagementmanager.utils.vvp_exceptions import VvpObjectNotAvailable, \ + VvpGeneralException, VvpBadRequest, VvpConflict +from itsdangerous import SignatureExpired +from requests import ConnectionError +from rest_framework import status +from rest_framework.exceptions import MethodNotAllowed, NotAuthenticated, \ + PermissionDenied, NotAcceptable + + +class ExceptionMessageFactory: + messages_dictionary = { + ObjectDoesNotExist.__name__: {'msg': 'User or Password does not match', 'include_exception': False, + 'status': status.HTTP_404_NOT_FOUND}, + MethodNotAllowed.__name__: {'msg': 'Method not allowed: ', 'include_exception': True, + 'status': status.HTTP_405_METHOD_NOT_ALLOWED}, + NotAuthenticated.__name__: {'msg': 'You must authenticate in order to perform this action: ', + 'include_exception': True, 'status': status.HTTP_403_FORBIDDEN}, + SignatureExpired.__name__: {'msg': 'Signature expired for this token: ', 'include_exception': True, + 'status': status.HTTP_405_METHOD_NOT_ALLOWED}, + KeyError.__name__: {'msg': 'KeyError occurred over the backend.', 'include_exception': True, + 'include_additional_exc_str': True, 'status': status.HTTP_400_BAD_REQUEST}, + ValueError.__name__: {'msg': 'ValueError occurred over the backend: ', 'include_exception': True, + 'status': status.HTTP_500_INTERNAL_SERVER_ERROR}, + ConnectionError.__name__: {'msg': 'ConnectionError occurred over the backend: ', 'include_exception': True, + 'status': status.HTTP_500_INTERNAL_SERVER_ERROR}, + ImportError.__name__: {'msg': 'ImportError occurred over the backend: ', 'include_exception': True, + 'status': status.HTTP_500_INTERNAL_SERVER_ERROR}, + CommandError.__name__: {'msg': 'CommandError occurred over the backend: ', 'include_exception': True, + 'status': status.HTTP_500_INTERNAL_SERVER_ERROR}, + PermissionDenied.__name__: {'msg': 'PermissionDenied occurred over the backend: ', 'include_exception': True, + 'status': status.HTTP_401_UNAUTHORIZED}, + VvpObjectNotAvailable.__name__: {'msg': '', 'include_exception': True, 'status': status.HTTP_410_GONE}, + NotAcceptable.__name__: {'msg': '', 'include_exception': True, 'status': status.HTTP_403_FORBIDDEN}, + VvpGeneralException.__name__: {'msg': '', 'include_exception': True, + 'status': status.HTTP_500_INTERNAL_SERVER_ERROR}, + FileExistsError.__name__: {'msg': 'Not modified due to: ', 'include_exception': True, + 'status': status.HTTP_304_NOT_MODIFIED}, + VvpBadRequest.__name__: {'msg': '', 'include_exception': True, 'status': status.HTTP_400_BAD_REQUEST}, + VvpConflict.__name__: {'msg': '', 'include_exception': True, 'status': status.HTTP_409_CONFLICT}, + Exception.__name__: {'msg': 'General error on backend: ', 'include_exception': True, + 'status': status.HTTP_500_INTERNAL_SERVER_ERROR}, + } + + def get_exception_message(self, exception): + if isinstance(exception, ObjectDoesNotExist): + result = self.messages_dictionary[ObjectDoesNotExist.__name__] + elif exception.__class__.__name__ in self.messages_dictionary: + result = self.messages_dictionary[exception.__class__.__name__] + else: + result = self.messages_dictionary[Exception.__name__] + + return result diff --git a/django/engagementmanager/utils/request_data_mgr.py b/django/engagementmanager/utils/request_data_mgr.py new file mode 100755 index 0000000..46557b4 --- /dev/null +++ b/django/engagementmanager/utils/request_data_mgr.py @@ -0,0 +1,128 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import threading +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class RequsetData(): + _thread_id = None + _cl_uuid = None + _eng_uuid = None + _user = None + _ns_uuid = None + _notification_uuid = None + + def __init__(self): + pass + + +class RequsetDataMgr: + + threadLocal = threading.local() + + ''' + Managing the request data per each request + ''' + + def __init__(self): + pass + + ''' + Private method + ''' + + def get_request_data(self): + request_data = getattr(self.threadLocal, 'request_data', None) + if request_data is None: + request_data = RequsetData() + self.threadLocal.request_data = request_data + + return request_data + + def get_user(self): + return self.get_request_data()._user + + def get_eng_uuid(self): + return self.get_request_data()._eng_uuid + + def get_cl_uuid(self): + return self.get_request_data()._cl_uuid + + def get_ns_uuid(self): + return self.get_request_data()._ns_uuid + + def get_notification_uuid(self): + return self.get_request_data()._notification_uuid + + def set_user(self, user): + self.get_request_data()._user = user + + def set_eng_uuid(self, eng_uuid): + self.get_request_data()._eng_uuid = eng_uuid + + def set_cl_uuid(self, cl_uuid): + self.get_request_data()._cl_uuid = cl_uuid + + def set_ns_uuid(self, ns_uuid): + self.get_request_data()._ns_uuid = ns_uuid + + def set_notification_uuid(self, notification_uuid): + self.get_request_data()._notification_uuid = notification_uuid + + def get_request_data_vars(self): + return { + 'cl_uuid': self.get_request_data()._cl_uuid, + 'eng_uuid': self.get_request_data()._eng_uuid, + 'user': self.get_request_data()._user, + 'ns_uuid': self.get_request_data()._ns_uuid, + 'notification_uuid': self.get_request_data()._notification_uuid, + } + + ''' + Called from the verify_token decorator which is a central place that populates the user and all other attributes in RequestData object + ''' + + def clear_old_request_data(self): + self.threadLocal.request_data = RequsetData() + + +# singleton pattern, allocated on server startup +request_data_mgr = RequsetDataMgr() diff --git a/django/engagementmanager/utils/validator.py b/django/engagementmanager/utils/validator.py new file mode 100755 index 0000000..cef67f6 --- /dev/null +++ b/django/engagementmanager/utils/validator.py @@ -0,0 +1,90 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +''' +Taken from https://pypi.python.org/pypi/validate_email +''' +import re +import bleach +from validate_email import validate_email +from engagementmanager.utils.vvp_exceptions import VvpBadRequest +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +class Validator(object): + + @staticmethod + def validateEmail(email): + if not validate_email(email): + msg = "email address validation error" + logger.error(msg) + raise KeyError(msg) + + @staticmethod + def validatePassword(password, confirm_password=False): + if confirm_password is not False and password != confirm_password: + msg = "'Password' and 'Confirm Password' do not match." + logger.error(msg) + raise VvpBadRequest(msg) + if len(password) < 4: + msg = "'Password' must be more than 4 letters." + logger.error(msg) + raise VvpBadRequest(msg) + if len(password) > 32: + msg = "'Password' must be less than 32 letters" + logger.error(msg) + raise VvpBadRequest(msg) + + @staticmethod + def validateCheckListName(name): + regex_pattern = "^[a-zA-Z0-9\&\ ]*$" + pattern = re.compile(regex_pattern) + + return pattern.match(name) + + +def logEncoding(data): + try: + clean_data = bleach.clean(str(data)) + clean_data += " (User Input)" + except Exception as e: + clean_data = "couldnt bleach data" + pass + return clean_data diff --git a/django/engagementmanager/utils/vvp_exceptions.py b/django/engagementmanager/utils/vvp_exceptions.py new file mode 100755 index 0000000..2cc9cee --- /dev/null +++ b/django/engagementmanager/utils/vvp_exceptions.py @@ -0,0 +1,66 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from rest_framework import status +from rest_framework.exceptions import APIException + +"""Custom exceptions for VVP project""" + + +class VvpBadRequest(APIException): + status_code = status.HTTP_400_BAD_REQUEST + default_detail = 'Bad request.' + default_code = 'bad_request' + + +class VvpObjectNotAvailable(APIException): + status_code = status.HTTP_410_GONE + default_detail = 'Bad request.' + default_code = 'bad_request' + + +class VvpGeneralException(APIException): + status_code = status.HTTP_500_INTERNAL_SERVER_ERROR + default_detail = 'Bad request.' + default_code = 'bad_request' + + +class VvpConflict(APIException): + status_code = status.HTTP_409_CONFLICT + default_detail = 'Conflic.' + default_code = 'conflict' diff --git a/django/engagementmanager/views_helper.py b/django/engagementmanager/views_helper.py new file mode 100755 index 0000000..418290b --- /dev/null +++ b/django/engagementmanager/views_helper.py @@ -0,0 +1,347 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.conf import settings +from django.utils import timezone +from engagementmanager.apps import bus_service +from engagementmanager.bus.messages.activity_event_message import \ + ActivityEventMessage +from engagementmanager.slack_client.api import SlackClient +from engagementmanager.models import IceUserProfile, Engagement, \ + DeploymentTarget, VF, Role, NextStep, ECOMPRelease +from engagementmanager.serializers import VFModelSerializer +from engagementmanager.service.checklist_state_service import \ + insert_to_recent_engagements +from engagementmanager.service.engagement_service import \ + update_or_insert_to_recent_engagements +from engagementmanager.service.logging_service import LoggingServiceFactory +from engagementmanager.service.nextstep_service import NextStepSvc +from engagementmanager.utils.constants import Constants, NextStepType, \ + NextStepState, RecentEngagementActionType, Roles +from engagementmanager.utils.activities_data import \ + UserJoinedEngagementActivityData +from engagementmanager.utils.validator import logEncoding +from engagementmanager.vm_integration import vm_client +import random +import re + + +logger = LoggingServiceFactory.get_logger() + + +def addEntityIfNotExist(entity, entityObj): + entResultSet = entity.objects.filter(uuid=entityObj.uuid) + + if entResultSet.exists(): + logger.debug(str(entityObj) + " Exists with UUID |" + entityObj.uuid) + was_created = False + else: + entityObj.save() + was_created = True + + return entity.objects.get(uuid=entityObj.uuid), was_created + + +def createEngagement(user, manual_el_id=False): + eng_manual_id = str(timezone.now().year) + "-" + \ + str(Engagement.objects.count() + 31) + eng = Engagement( + engagement_manual_id=eng_manual_id, creator=user) + elUser = None + randUser = None + elRole = Role.objects.get(name=Roles.el.name) # @UndefinedVariable + if user.role == elRole: + manual_el_id = user.email + + # Attaching EL and Peer Reviewer to the Engagment + if user.role != elRole: + if not manual_el_id: + # Fetch a random EL + qs = IceUserProfile.objects.all().filter(role=elRole) # @UndefinedVariable + if qs.count() > 0: + randUser = qs[random.randint(0, qs.count() - 1)] + elUser = IceUserProfile.objects.get(uuid=randUser.uuid) + else: + # Set el manually, for example when using import from xls el is + # already assigned + elUser = IceUserProfile.objects.get(email=manual_el_id) + else: + logger.debug("Since the user " + user.full_name + + " is an EL, no need to find another one") + elUser = user + + logger.debug("Selected engagement lead=" + elUser.full_name) + eng.reviewer = elUser + + # Fetch another random el to be a Peer Reviewer + qs = IceUserProfile.objects.all().filter( + role=elRole, user__is_active=True).exclude(uuid=elUser.uuid) # @UndefinedVariable + prUser = None + if qs.count() > 0: + randUser = qs[random.randint(0, qs.count() - 1)] + prUser = IceUserProfile.objects.get(uuid=randUser.uuid) + eng.peer_reviewer = prUser + logger.debug("Selected peer reviewer=" + prUser.full_name) + + engObj, was_created = addEntityIfNotExist(Engagement, eng) + + return engObj, elUser, prUser + + +def is_str_supports_git_naming_convention(item): + """ + validates that string can contain only letters, digits hyphen and dot. Also, String cannot end with dot + """ + return bool(re.compile("^[a-zA-Z0-9-]*$").match(item)) + + +def createVF(user, request): + """ + Create DeploymentTarget + Create Engagement + Create Application_Service_Infrastructure + Create VF + """ + dataList = request.data + vfList = [] + + for data in dataList: + logger.debug("Processing VF - " + str(data)) + + if ('virtual_function' not in data or not data['virtual_function'] or + 'version' not in data or not data['version'] or + 'target_lab_entry_date' not in data or not data['target_lab_entry_date'] or + 'target_aic_uuid' not in data or not data['target_aic_uuid'] or + 'ecomp_release' not in data or not data['ecomp_release'] or + 'is_service_provider_internal' not in data): + raise KeyError("One of the input parameters are missing") + + # Set el manually, for example when using import from xls el is + # already assigned + if 'manual_el_id' in data: + manual_el_id = data['manual_el_id'] + else: + manual_el_id = False + engObj, elUser, prUser = createEngagement(user, manual_el_id) + + if engObj is None or elUser is None: + raise ValueError("Couldn't fetch engagement or engagement lead") + + if user is not None and engObj is not None: + NextStepSvc().create_default_next_steps(user, engObj, elUser) + + i_target_aic_uuid = data['target_aic_uuid'] + dtObj = DeploymentTarget.objects.get(uuid=i_target_aic_uuid) + + i_ecomp_release = data['ecomp_release'] + ecompObj = ECOMPRelease.objects.get(uuid=i_ecomp_release) + + i_vfName = data['virtual_function'] + if not is_str_supports_git_naming_convention(i_vfName): + msg = "VF Name can contain only letters, digits hyphen and dot. VF Name cannot end with dot" + logger.error(msg) + raise ValueError(msg) + i_vfVersion = data['version'] + i_is_service_provider_internal = data['is_service_provider_internal'] + i_target_lab_entry_date = data['target_lab_entry_date'] + + vf = VF(name=i_vfName, + version=i_vfVersion, + engagement=engObj, + deployment_target=dtObj, + ecomp_release=ecompObj, + is_service_provider_internal=i_is_service_provider_internal, + vendor=user.company, + target_lab_entry_date=i_target_lab_entry_date + ) + + vfObj, was_created = addEntityIfNotExist(VF, vf) + + insert_to_recent_engagements( + user, RecentEngagementActionType.NEW_VF_CREATED.name, vfObj) # @UndefinedVariable + + addUsersToEngTeam(engObj.uuid, [user, elUser, prUser]) + sendSlackNotifications(engObj.uuid, [user, elUser, prUser]) + # trigger repo creation as soon as vf is created and users are added to + # team + if was_created: + vm_client.fire_event_in_bg('send_provision_new_vf_event', vfObj) + vfData = VFModelSerializer(vfObj).data + vfList.append(vfData) + + return vfList + + +def updateValidationDetails(request): + # if data['target_aic_uuid'] is not None and data['target_aic_uuid'] != "": + data = request.data + logger.debug("Processing VF_Details - " + str(data)) + vf = VF.objects.get(uuid=data['vf_uuid']) + if 'target_aic_uuid' in data: + dt_obj = DeploymentTarget.objects.get(uuid=data['target_aic_uuid']) + vf.deployment_target = dt_obj + if 'ecomp_release' in data: # is not None and data['ecomp_release'] != "": + ecomp_obj = ECOMPRelease.objects.get(uuid=data['ecomp_release']) + vf.ecomp_release = ecomp_obj + if 'version' in data: + vf.version = data['version'] + vf.save() + + +def checkAndModifyIfSSHNextStepExist(user): + SSHStep = None + qs = NextStep.objects.filter( + owner=user, next_step_type=NextStepType.set_ssh.name) # @UndefinedVariable + if qs is None or qs.count() == 0: + return None + else: + SSHStep = NextStep.objects.get( + owner=user, next_step_type=NextStepType.set_ssh.name) # @UndefinedVariable + + # @UndefinedVariable + if SSHStep.state in (NextStepState.Incomplete.name) and user.ssh_public_key: + SSHStep.state = 'Completed' + SSHStep.last_update_time = timezone.now() + SSHStep.last_update_type = 'Completed' + SSHStep.save() + + return SSHStep + + +def addUsersToEngTeam(eng_uuid, newUserList): + """ + If the user isn't an EL and their doesn't have an SSH step then create personal SSH next step for him. + """ + engObj = Engagement.objects.get(uuid=eng_uuid) + vfObj = engObj.vf + el_user = IceUserProfile.objects.get(uuid=engObj.reviewer.uuid) + if not el_user: + el_user = newUserList[1] + for newUser in newUserList: + engObj.engagement_team.add(newUser) + update_or_insert_to_recent_engagements( + newUser.uuid, vfObj, RecentEngagementActionType.JOINED_TO_ENGAGEMENT.name) # @UndefinedVariable + SSHStep = checkAndModifyIfSSHNextStepExist(newUser) + if not SSHStep and newUser != el_user: + NextStepSvc().create_default_next_steps_for_user(newUser, el_user) + if vfObj is not None: + activity_data = UserJoinedEngagementActivityData( + vfObj, newUserList, engObj) + bus_service.send_message(ActivityEventMessage(activity_data)) + + +def sendSlackNotifications(eng_uuid, newUserList): + """ + Send Slack notifications to the reviewer, peer reviewer and also the engagements channel + """ + # get the engagement + engagement = Engagement.objects.get(uuid=eng_uuid) + engagement_manual_id = "" + if engagement is not None: + engagement_manual_id = engagement.engagement_manual_id + + # get the vf + vf = VF.objects.get(engagement__uuid=eng_uuid) + vf_name = "" + if vf is not None: + vf_name = vf.name + + # get the creator + creator = engagement.creator + + # get the reviewer + reviewer = IceUserProfile.objects.get(uuid=engagement.reviewer.uuid) + if not reviewer: + reviewer = newUserList[1] + + # get the peer reviewer + peer_reviewer = IceUserProfile.objects.get( + uuid=engagement.peer_reviewer.uuid) + if not peer_reviewer: + peer_reviewer = newUserList[2] + + # send Slack messages when a new engagement is created + slack_client = SlackClient() + slack_client.send_slack_notifications_for_new_engagement( + engagement_manual_id, vf_name, reviewer, peer_reviewer, creator) + + +def getVfByEngUuid(engUuid): + vfList = VF.objects.filter(engagement__uuid=engUuid) + if vfList: + logger.debug("Found VF name=" + vfList[0].name) + if len(vfList) > 1: + logger.warning( + "!! There seems to be more than one VF attached to the engagement with uuid=" + logEncoding(engUuid)) + # Assumption: the list only has one item because the relation + # Engagement-VF is 1:1 business wise + return vfList[0] + else: + logger.error( + "There are no VFs in the engagement identified by eng_uuid=" + logEncoding(engUuid)) + return None + + +def generateActivationLink(activationToken, user): + return str(settings.DOMAIN) + Constants.activation_prefix + str(user.uuid) + "/" + activationToken + + +def getFirstEngByUser(user): + engList = Engagement.objects.filter(engagement_team__uuid=user.uuid) + if engList.exists(): + logger.debug("user was found in a an ENG:" + str(engList[0])) + return engList[0] + else: + logger.debug("user wasn't found in an ENG") + return None + + +def createUserTemplate(company, full_name, role, phone, is_service_provider_contact, ssh_key=None, regular_email_updates=False, user=None): + data = { + 'company': company, + 'phone_number': phone, + 'full_name': full_name, + 'role': role, + 'create_time': timezone.now(), + 'is_service_provider_contact': is_service_provider_contact, + 'regular_email_updates': regular_email_updates, + 'ssh_public_key': ssh_key, + } + if user: + data['user'] = user + return data diff --git a/django/engagementmanager/vm_integration/__init__.py b/django/engagementmanager/vm_integration/__init__.py new file mode 100755 index 0000000..1726c13 --- /dev/null +++ b/django/engagementmanager/vm_integration/__init__.py @@ -0,0 +1,38 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. diff --git a/django/engagementmanager/vm_integration/em_api.py b/django/engagementmanager/vm_integration/em_api.py new file mode 100755 index 0000000..b41a3ff --- /dev/null +++ b/django/engagementmanager/vm_integration/em_api.py @@ -0,0 +1,188 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +import json +from django.core.exceptions import ObjectDoesNotExist +from engagementmanager.slack_client.api import SlackClient +from engagementmanager.models import Checklist, VF +from engagementmanager.service.checklist_service import CheckListSvc +from engagementmanager.service.checklist_state_service import set_state +from engagementmanager.utils import dict_path_get +from engagementmanager.utils.constants import CheckListCategory, CheckListState, EngagementStage +from engagementmanager.utils.request_data_mgr import request_data_mgr +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() + + +def test_finished_callback(checklist_test_results): + logger.debug( + "test_finished_callback has signaled that a test has finished with test results %r", checklist_test_results) + + if not checklist_test_results: + msg = "Couldn't find payload argument inside kwargs array, aborting signal" + logger.error(msg) + raise KeyError(msg) + + checklist_test_results['description'] = "Validation manager has indicated that checklist {} tests has been completed with results".format( + checklist_test_results['checklist_uuid']) + + checklist = Checklist.objects.get( + uuid=checklist_test_results['checklist_uuid']) + request_data_mgr.set_cl_uuid(checklist.uuid) + data = CheckListSvc().setChecklistDecisionsFromValMgr( + user=checklist.owner, + checklist_uuid=checklist_test_results['checklist_uuid'], + decisions=checklist_test_results['decisions'], + checklist_results_from_jenkins=checklist_test_results + ) + return data + + +def git_push_callback(gitlab_data): + """ + When we are notified that a repo has received a push, we must reject any checklists not in the + closed or archived state whose associated files have been modified. + """ + logger.debug("Validation manager has signaled that a git push has occurred") + msg = "OK" + data = None + + # sanity check provided arguments + for key in ['project', 'project/git_ssh_url', 'commits']: + if not dict_path_get(gitlab_data, key): + msg = "{!r} in the git_push signal gitlab_data is missing or empty.".format( + key) + logger.error(msg) + raise KeyError(msg) + + # For now, ignore pushes made to any branch other than 'master'. + if gitlab_data['ref'] != u'refs/heads/master': + logger.warn("A non-master ref %r was updated. Ignoring.", + gitlab_data['ref']) + return None + + # sanity check payload data + if int(gitlab_data['total_commits_count']) == 0: + logger.debug("total_commits_count = %s", + gitlab_data['total_commits_count']) + msg = "Something is wrong: Number of commits is 0 even after a push event has been invoked from validation manager to engagement manager" + logger.warn(msg) + raise ValueError(msg) + + if gitlab_data['before'] == '0000000000000000000000000000000000000000': + logger.debug('This is the first commit pushed to master.') + + git_ssh_url = gitlab_data['project']['git_ssh_url'] + + vf = VF.objects.filter(git_repo_url=git_ssh_url) + + if len(vf) == 0: + msg = "Couldn't fetch any VF" + logger.error(msg) + raise ObjectDoesNotExist(msg) + else: + vf = VF.objects.get(git_repo_url=git_ssh_url) + + checklists = (Checklist.objects + .filter(engagement=vf.engagement) + # @UndefinedVariable + .exclude(state=CheckListState.archive.name) + .exclude(state=CheckListState.closed.name)) # @UndefinedVariable + + committed_files = set(file + for commit in gitlab_data['commits'] + for status in ['added', 'modified', 'removed'] + for file in commit[status]) + logger.debug("Committed files list: [%s]" % ', '.join(committed_files)) + + # send notifications to reviewers and peer reviewers when the git repo is + # updated + vf_name = vf.name + engagement_manual_id = vf.engagement.engagement_manual_id + reviewer = vf.engagement.reviewer + peer_reviewer = vf.engagement.peer_reviewer + slack_client = SlackClient() + slack_client.send_notifications_on_git_push( + engagement_manual_id, vf_name, reviewer, peer_reviewer, committed_files) + + # loop through the checklists and start automation if necessary + for checklist in checklists: + user = checklist.owner + template_category = checklist.template.category + mutual_files = committed_files.intersection( + json.loads(checklist.associated_files)) + logger.debug("Mutual files list for checklist %s: [%s]" % ( + checklist.uuid, ', '.join(committed_files))) + if not mutual_files and\ + template_category == CheckListCategory.heat.name and\ + not any(file + for file in committed_files + for extension in ['.yaml', '.yml', '.env'] + if file.lower().endswith(extension)): + continue + if checklist.state == CheckListState.pending.name: # @UndefinedVariable + description = "Checklist {checklist.name} (part of VF {vf.name}/{vf.uuid}) in Pending state will transition to Automation due to a push action on files [{mutual_files}]. chosen EL: {user.full_name}".format( + checklist=checklist, + vf=vf, + mutual_files=", ".join(mutual_files), + user=user, + ) + else: + description = "Checklist {checklist.uuid} (part of VF {vf.name}/{vf.uuid}) has been rejected due to a push action made on files [{mutual_files}]. chosen EL is: {user.full_name}".format( + checklist=checklist, + vf=vf, + mutual_files=", ".join(mutual_files), + user=user, + ) + logger.debug(description) + # FIXME Setting parameters into a global before calling a function that will break without + # them is TERRIBLE. We must fix this before we open-source this code. + request_data_mgr.set_cl_uuid(checklist.uuid) + request_data_mgr.set_user(user) + data = set_state( # means that the checklist will be declined and a cloned one is + # created in PENDING status + decline=True, + checklist_uuid=checklist.uuid, + # means the checklist will be triggered into automation cycle + isMoveToAutomation=True, + description="This change was triggered by an update to the engagement git repository.") + + logger.debug("set_state returned (%r)" % data) + + return data diff --git a/django/engagementmanager/vm_integration/vm_client.py b/django/engagementmanager/vm_integration/vm_client.py new file mode 100755 index 0000000..04d77c5 --- /dev/null +++ b/django/engagementmanager/vm_integration/vm_client.py @@ -0,0 +1,152 @@ +# +# ============LICENSE_START========================================== +# org.onap.vvp/engagementmgr +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +from django.conf import settings +from django.db.models import Q +from engagementmanager.apps import bus_service +from engagementmanager.bus.messages.activity_event_message import \ + ActivityEventMessage +from engagementmanager.models import VF, Role, IceUserProfile +from engagementmanager.utils.constants import Roles +from engagementmanager.utils.activities_data import \ + VFProvisioningActivityData +import concurrent.futures +import validationmanager.em_integration.vm_api as vm_api +from engagementmanager.service.logging_service import LoggingServiceFactory + +logger = LoggingServiceFactory.get_logger() +executor = concurrent.futures.ThreadPoolExecutor(max_workers=4) + + +def send_jenkins_job_and_gitlab_repo_exists(vf): + # A signal which check if jenkins job was created and also if gitlab repo + logger.debug( + "Sending a call to validation manager. Call=jenkins_job_and_gitlab_repo_exists_callback. vf=%s", vf.uuid) + is_ready = vm_api.jenkins_job_and_gitlab_repo_exists_callback(vf=vf) + return is_ready + + +def send_cl_from_pending_to_automation_event(checkListObj): + # A signal that is sent when Engagement MAnager moves CL from Pending to + # Automation (for example when a CL is rejected by other signal from + # validation manager) + vf = VF.objects.get(engagement=checkListObj.engagement) + logger.debug( + "Sending a call to validation manager. Call=send_cl_from_pending_to_automation_event. checklistUuid=%s", checkListObj.uuid) + vm_api.cl_from_pending_to_automation_callback(vf=vf, checklist=checkListObj) + + +def send_ssh_key_created_or_updated_event(user): + # A signal which is sent from the EM to the VM when a user is adding or + # updating their ssh key + logger.debug( + "Sending a call to validation manager. Call=send_ssh_key_created_or_updated_event. user=%s", user.uuid) + vm_api.ssh_key_created_or_updated_callback(user=user) + +def send_create_user_in_rgwa_event(user): + # A signal which is sent from the EM to the VM when a user is adding or + # updating their ssh key + logger.debug( + "Sending a call to validation manager. Call=send_create_user_in_rgwa_event. user=%s", user.full_name) + vm_api.create_user_rgwa(user=user) + + +def send_remove_all_standard_users_from_project_event(gitlab, project_id, formatted_vf): + logger.debug( + "Sending a call to validation manager. Call=send_remove_all_standard_users_from_project_event.") + vm_api.remove_all_standard_users_from_project( + gitlab, project_id, formatted_vf) + + +def send_get_project_by_vf_event(vf, gitlab): + if not settings.IS_SIGNAL_ENABLED: + return None + logger.debug( + "Sending a call to validation manager. Call=send_get_project_by_vf_event.") + vm_api.get_project_by_vf(vf, gitlab) + + +def send_provision_new_vf_event(vf): + # A signal which is sent from the EM to the VM when a new VF is created. VM will than create a + # gitlab repo for that new VF. + # + # Note: despite its name, this signal is not used only for new vfs, but to update existing gitlab + # and jenkins provisioning when a vf changes e.g. when team members are + # added or removed. + try: + vm_api.provision_new_vf_callback(vf=vf) + logger.debug( + "Sending a call to validation manager. Call=send_provision_new_vf_event. vf=%s", vf.uuid) + except Exception as e: + el_role = Role.objects.get(name=Roles.el.name) # @UndefinedVariable + admin_role = Role.objects.get( + name=Roles.admin.name) # @UndefinedVariable + el_admin_list = IceUserProfile.objects.all().filter( + Q(role=el_role) | Q(role=admin_role)) + activity_data = VFProvisioningActivityData( + vf, el_admin_list, vf.engagement, e) + bus_service.send_message(ActivityEventMessage(activity_data)) + + +def send_get_list_of_repo_files_event(vf): + # A signal which is sent from the EM to the VM when a NextStep is created + # and we need the VF associated files in the git repository + files = vm_api.get_list_of_repo_files_callback(vf=vf) + logger.debug( + "Sending a call to validation manager. Call=send_get_list_of_repo_files_event. vf=%s", vf.uuid) + + formatted_repo_files = [] + + for file in files: + formatted_repo_files.append(file['name']) + logger.debug(file['name']) + + return formatted_repo_files + + +''''''''''''''''''''''''''' + UTIL FUNCTIONS FOR SIGNALS +''''''''''''''''''''''''''' + + +def fire_event_in_bg(function_name, obj): + event_function = globals()[function_name] + logger.debug( + " . . . . . . . . . . . . Fire event in background started: %s . . . . . . . . . . . . ", function_name) + future = executor.submit(event_function, obj) + logger.debug("Main thread continue without blocking...") |