Skip to content

send a we miss you message to inactive users #447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions api_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,36 @@ paths:
500:
description: "Internal Server Error"

"/users/inactive_user_reminder":
post:
tags:
- inactive_user_reminder
consumes:
- application/json
parameters:
- in: header
name: Authorization
required: true
description: "Bearer [token]"
- in: body
name: inactive_user_reminder
schema:
type: object
required:
- inactive_users
properties:
inactive_users:
type: array<user>
produces:
- application/json
responses:
201:
description: "Success"
400:
description: "Bad request"
500:
description: "Internal Server Error"

"/clusters":
post:
tags:
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from .users import (
UsersView, UserLoginView, UserEmailVerificationView,
EmailVerificationRequest, ForgotPasswordView, ResetPasswordView,
UserDetailView, AdminLoginView, OAuthView, UserDataSummaryView, UserAdminUpdateView, UserActivitesView, InActiveUsersView)
UserDetailView, AdminLoginView, OAuthView, UserDataSummaryView, UserAdminUpdateView, UserActivitesView, InActiveUsersView, SendInactiveUserMailReminder)
from .deployments import DeploymentsView
from .clusters import (
ClustersView, ClusterDetailView, ClusterNamespacesView,
Expand Down
56 changes: 56 additions & 0 deletions app/controllers/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from app.models.role import Role
from app.helpers.confirmation import send_verification
from app.helpers.token import validate_token
from app.helpers.inactive_notification import send_inactive_notification_to_user
from app.schemas import ProjectSchema, AppSchema
from app.helpers.decorators import admin_required
import requests
Expand Down Expand Up @@ -1097,3 +1098,58 @@ def get(self):
status='success',
data=dict(pagination=pagination, users=json.loads(users_data))
), 200

class SendInactiveUserMailReminder(Resource):

@admin_required
def post(self):
# Get the list of inactive users from the request body
user_schema = UserSchema()

user_data = request.get_json()

validated_user_data, errors = user_schema.load(user_data)

today = datetime.now()

if errors:
return dict(status="fail", message=errors), 400

if 'inactive_users' not in validated_user_data:
return dict(status='fail', message='Inactive users data not provided in the request'), 400

inactive_users = validated_user_data['inactive_users']

for user_data in inactive_users:
user = User.query.get(user_data['uuid']) # Assuming there's a unique identifier like 'id'

if user is None:
continue

# Check if a reminder email was sent in the last month
if user.last_reminder_sent is None or user.last_reminder_sent < (datetime.now() - timedelta(days=30)):

# send email variable
name = user.name
template = "user/inactive_user_reminder.html"
subject = "We miss you at Crane Cloud"
email =user.email
today = today.date
success = False

# send email
success = True
send_inactive_notification_to_user(
email,
name,
current_app._get_current_object(),
template,
subject,
today.strftime("%m/%d/%Y"),
success)

user.last_reminder_sent = today.date()
db.session.commit()

return dict(status='success', message='Reminder emails sent successfully')

15 changes: 15 additions & 0 deletions app/helpers/inactive_notification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask import render_template
from .email import send_email
from flask import Flask, request


def send_inactive_notification_to_user( email, name, app, template, subject, date, success):
client_base_url = f'https://{request.host}'
html = render_template(template,
email=email,
client_base_url=client_base_url,
name=name,
date= date,
success=success)
subject = subject
send_email(email, subject, html, email, app)
1 change: 1 addition & 0 deletions app/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class User(ModelMixin):
verified = db.Column(db.Boolean, nullable=False, default=False)
date_created = db.Column(db.DateTime, default=db.func.current_timestamp())
last_seen = db.Column(db.DateTime, default=db.func.current_timestamp())
last_reminder_sent = db.Column(db.DateTime, default=db.func.current_timestamp())
projects = db.relationship('Project', backref='owner', lazy=True)
organisation = db.Column(db.String(256), nullable=True, default="")
other_projects = db.relationship('ProjectUser', back_populates='user')
Expand Down
5 changes: 3 additions & 2 deletions app/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from flask_restful import Api
from app.controllers import (
IndexView, UsersView, UserLoginView, OAuthView, DeploymentsView, RolesView, InActiveUsersView,
IndexView, UsersView, UserLoginView, OAuthView, DeploymentsView, RolesView, InActiveUsersView, SendInactiveUserMailReminder,
RolesDetailView, CreditAssignmentView, CreditAssignmentDetailView, CreditView, UserRolesView, UserDataSummaryView, ClustersView,
ClusterDetailView, ClusterNamespacesView,
ClusterNamespaceDetailView, ClusterNodesView, ClusterNodeDetailView,
Expand Down Expand Up @@ -43,7 +43,8 @@
api.add_resource(UserActivitesView, '/users/activities')
api.add_resource(InActiveUsersView, '/users/inactive_users',
endpoint='inactive_users')

api.add_resource(SendInactiveUserMailReminder, '/users/inactive_user_reminder',
endpoint='inactive_user_reminder')

# Deployments
api.add_resource(DeploymentsView, '/deployments', endpoint='deployments')
Expand Down
140 changes: 140 additions & 0 deletions templates/user/inactive_user_reminder.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<!DOCTYPE html>
<html>

<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<style type="text/css">
body,
table,
td,
a {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}

table,
td {
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}

img {
-ms-interpolation-mode: bicubic;
}

/* RESET STYLES */
img {
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
}

table {
border-collapse: collapse !important;
}

body {
height: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
}

/* iOS BLUE LINKS */
a[x-apple-data-detectors] {
color: inherit !important;
text-decoration: none !important;
font-size: inherit !important;
font-family: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
}

/* MOBILE STYLES */
@media screen and (max-width: 600px) {
h1 {
font-size: 32px !important;
line-height: 32px !important;
}
}

/* ANDROID CENTER FIX */
div[style*="margin: 16px 0;"] {
margin: 0 !important;
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Open+Sans&family=Roboto:ital,wght@1,500&display=swap" rel="stylesheet">

<style>
body {
font-family: 'Roboto', sans-serif;
}
</style>
</head>

<body style="background-color: #f4f4f4; margin: 0 !important; padding: 0 !important;">
<!-- HIDDEN PREHEADER TEXT -->
<div style="display: none; font-size: 1px; color: #fefefe; line-height: 1px; max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden;"> We're thrilled to have you here! Get ready to dive into your new account. </div>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td bgcolor="#f4f4f4" align="center" style="padding: 0px 10px 0px 10px;">
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
<tr>
<td bgcolor="#ffffff" align="center" valign="top"
style="padding: 5px 15px 30px 15px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Roboto', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcRzkuTpE0q2DJnKC3XJMbmMUA_WZRYcBlefOHSmgMp71IukHAgx&usqp=CAU"
width="150" height="100" style="display: block; border: 0px;" />
<h1 style="font-size: 48px; font-weight: 400; margin: 2;">{{ name }}</h1>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#f4f4f4" align="center" style="padding: 0px 10px 0px 10px;">
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
<tr>

<td bgcolor="#ffffff" align="left"
style="padding: 5px 15px 30px 15px; color: #666666; font-family: 'Roboto', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;">
<p style="margin: 0;"> We miss you at Crane Cloud. Get ready to dive into your account. Let's help you get started. Just press the button below.</p>
</td>
</tr>
<tr>
<td bgcolor="#ffffff" align="left">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td bgcolor="#ffffff" align="center"
style="padding: 5px 15px 30px 15px;">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td align="center" style="border-radius: 3px;"
bgcolor="#008AC1"><a href="{{ client_base_url }}"
target="_blank"
style="font-size: 20px; font-family: 'Roboto', Arial, sans-serif; color: #ffffff; text-decoration: none; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #008AC1; display: inline-block;">Visit Crane Cloud
</a></td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#ffffff" align="left"
style="padding: 0px 30px 40px 30px; border-radius: 0px 0px 4px 4px; color: #666666; font-family: 'Roboto', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;">
<p style="margin: 0;">Cheers!<br>Crane Cloud Team</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>

</html>