-
Notifications
You must be signed in to change notification settings - Fork 229
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #437 from Thisara-Welmilla/add-notification-extern…
…al-schedular Add notification-sender-external-schedular sample.
- Loading branch information
Showing
6 changed files
with
249 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"email_configurations": { | ||
"sender_email": "<SENDER_EMAIL>", | ||
"sender_password": "<SENDER_PASSWORD>", | ||
"smtp_server": "<SMTP_SERVER>", | ||
"smtp_port": 587 | ||
}, | ||
|
||
"is_server_config": { | ||
"client_id": "<CLIENT_ID>", | ||
"client_secret": "<CLIENT_SECRET>", | ||
"organization": "<ORG_NAME>", | ||
"hostname": "<HOSTNAME>", | ||
"alert_before_in_days": 3 | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
etc/notification-sender-ext-schedular/configuration_manager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# | ||
# Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). | ||
# | ||
# WSO2 LLC. licenses this file to you under the Apache License, | ||
# Version 2.0 (the "License"); you may not use this file 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. | ||
# | ||
|
||
import json | ||
|
||
# This is the class which read and hold configurations from the configuration file. | ||
class configuration_manager: | ||
def __init__(self, config_file): | ||
try: | ||
with open(config_file, 'r') as file: | ||
self.config_data = json.load(file) | ||
except FileNotFoundError: | ||
raise FileNotFoundError(f"Config file '{config_file}' not found.") | ||
except json.JSONDecodeError: | ||
raise ValueError(f"Error decoding JSON in '{config_file}'.") | ||
|
||
# This method is to retrieve the configurations of the email sender. | ||
def get_email_notification_manager_config(self): | ||
|
||
return self.config_data["email_configurations"] | ||
|
||
# This method is to retrieve the configurations of the WSO2 IS Server. | ||
def get_is_server_config(self): | ||
|
||
return self.config_data["is_server_config"] | ||
|
50 changes: 50 additions & 0 deletions
50
etc/notification-sender-ext-schedular/email_notification_manager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# | ||
# Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). | ||
# | ||
# WSO2 LLC. licenses this file to you under the Apache License, | ||
# Version 2.0 (the "License"); you may not use this file 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. | ||
# | ||
|
||
import smtplib | ||
import logging | ||
from email.mime.text import MIMEText | ||
from email.mime.multipart import MIMEMultipart | ||
|
||
email_subject = "Your Password Has Expired" | ||
email_body = "Hi there,\n\nYour password has been expired. Please reset your password." | ||
|
||
# This is the class which reposibe for sending email notifications. | ||
class email_notification_manager: | ||
def __init__(self, email_config): | ||
self.smtp_server = email_config["smtp_server"] | ||
self.smtp_port = email_config["smtp_port"] | ||
self.sender_email = email_config["sender_email"] | ||
self.sender_password = email_config["sender_password"] | ||
|
||
# This method is to send the email to the given email address. | ||
def send_email(self, reciever_email): | ||
|
||
message = MIMEMultipart() | ||
message['From'] = self.sender_email | ||
message['To'] = reciever_email | ||
message['Subject'] = email_subject | ||
message.attach(MIMEText(email_body, 'plain')) | ||
|
||
# Connect to SMTP server and send email | ||
with smtplib.SMTP(self.smtp_server, self.smtp_port) as server: | ||
server.starttls() | ||
server.login(self.sender_email, self.sender_password) | ||
|
||
server.sendmail(self.sender_email, reciever_email, message.as_string()) | ||
logging.info("Passowrd expired notification is send to the email address:" + reciever_email) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# | ||
# Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). | ||
# | ||
# WSO2 LLC. licenses this file to you under the Apache License, | ||
# Version 2.0 (the "License"); you may not use this file 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. | ||
# | ||
|
||
import azure.functions as func | ||
import logging | ||
from configuration_manager import * | ||
from email_notification_manager import * | ||
from is_server_utils import * | ||
|
||
app = func.FunctionApp() | ||
config_manager = configuration_manager("config.json") | ||
is_utils = is_server_utils(config_manager.get_is_server_config()) | ||
notification_manager = email_notification_manager(config_manager.get_email_notification_manager_config()) | ||
|
||
@app.schedule(schedule="0 0 */2 * * *", arg_name="myTimer", run_on_startup=True, | ||
use_monitor=False) | ||
def timer_trigger(myTimer: func.TimerRequest) -> None: | ||
if myTimer.past_due: | ||
logging.info('The timer is past due!') | ||
|
||
logging.info("***************** Starting the schedular task *****************") | ||
is_utils.get_access_token() | ||
passowrd_expired_users = is_utils.get_password_expired_user_list() | ||
|
||
# Send email to each user whose password has been expired. | ||
for user in passowrd_expired_users: | ||
user_id = user["userId"] | ||
reciever_email = is_utils.get_email_address(user_id) | ||
notification_manager.send_email(reciever_email) | ||
|
||
logging.info("***************** Completed the schedular task *****************") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# | ||
# Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). | ||
# | ||
# WSO2 LLC. licenses this file to you under the Apache License, | ||
# Version 2.0 (the "License"); you may not use this file 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. | ||
# | ||
|
||
import json | ||
import logging | ||
import requests | ||
import sys | ||
from datetime import datetime, timedelta | ||
|
||
# This is the class which contains the utils for the WOS2 IS Server. | ||
class is_server_utils: | ||
def __init__(self, is_server_config): | ||
|
||
self.access_token = None | ||
|
||
# IS Server related configurations. | ||
self.client_key = is_server_config["client_id"] | ||
self.client_password = is_server_config["client_secret"] | ||
self.organization = is_server_config["organization"] | ||
self.hostname = is_server_config["hostname"] | ||
self.alert_before_in_days = is_server_config["alert_before_in_days"] | ||
|
||
# IS server APIs. | ||
self.inactive_user_retrieval_endpoint_url = f"https://{self.hostname}/t/{self.organization}/api/server/v1/password-expired-users" | ||
self.user_scim2_endpoint = f"https://{self.hostname}/t/{self.organization}/scim2/Users/" | ||
self.token_endpoint = f"https://{self.hostname}/t/{self.organization}/oauth2/token" | ||
self.required_scope_list = "SYSTEM" | ||
|
||
# This method is to retrieve the access token with client credentials. | ||
def get_access_token(self): | ||
|
||
data = { | ||
"grant_type": "client_credentials", | ||
"scope": self.required_scope_list | ||
} | ||
headers = { | ||
"Content-Type": "application/x-www-form-urlencoded" | ||
} | ||
response = requests.post(self.token_endpoint, data=data, headers=headers, auth=(self.client_key, self.client_password)) | ||
|
||
if response.status_code != 200: | ||
logging.error("Error occured while obtaining an access token. Response: " + json.dumps(response.json())) | ||
sys.exit() | ||
|
||
self.access_token = response.json()["access_token"] | ||
|
||
# This method is to retrieve the list of user Ids whose password has been expired. | ||
def get_password_expired_user_list(self): | ||
|
||
expired_after = datetime.now() + timedelta(days=self.alert_before_in_days) | ||
exclude_after = expired_after + timedelta(days=1) | ||
|
||
params = {'expiredAfter': expired_after.strftime("%Y-%m-%d"), 'excludeAfter': exclude_after.strftime("%Y-%m-%d")} | ||
headers = {'Authorization': f'Bearer {self.access_token}'} | ||
response = requests.get(self.inactive_user_retrieval_endpoint_url, params=params, headers=headers) | ||
|
||
if response.status_code != 200: | ||
logging.error("Error occured while obtaining an password expired users. Response: " + json.dumps(response.json())) | ||
sys.exit() | ||
|
||
return response.json() | ||
|
||
# This method is to retrieve the email address for the given user Id. | ||
def get_email_address(self, user_id): | ||
|
||
headers = {'Authorization': f'Bearer {self.access_token}'} | ||
response = requests.get(self.user_scim2_endpoint + user_id, headers=headers) | ||
|
||
if response.status_code != 200: | ||
logging.error("Error occured while obtaining an password expired users. Response: " + json.dumps(response.json())) | ||
sys.exit() | ||
|
||
return response.json()["emails"][0] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# DO NOT include azure-functions-worker in this file | ||
# The Python Worker is managed by Azure Functions platform | ||
# Manually managing azure-functions-worker may cause unexpected issues | ||
|
||
azure-functions | ||
secure-smtplib | ||
emails |