Skip to content

Commit 8f5feca

Browse files
gloriajwjenkins-fansUpstage system userTuyetGiang
authored
Update devapp1.yml (#1000)
* Update devapp1.yml New release * small bug fixes in async code. rename ov event svc and script fix * small bug fixes in async code. rename ov event svc and script fix * perms * Bringing Phat's changes into current branch. * Enhance send email from client server (#1013) * Enhance send email from client server * Change using email queue to call service * Add toggle enable donate for Upstage (#1012) * Add readme about send email * Revert user_schema * update email process * change default setting * update process send email * update READme * Move Donate toggle from system to foyer * Fetch Stages after login (#1016) * Fix fetchStage after login * Fix send email external format Co-authored-by: gloriajw <aagg@comcast.net> Co-authored-by: Upstage system user <upstage@app1.upstage.org.nz-1621696771938-s-2vcpu-4gb-nyc1-01> Co-authored-by: TuyetGiang <30744004+TuyetGiang@users.noreply.github.com> Co-authored-by: giang <giang281197@gmail.com>
1 parent 1820798 commit 8f5feca

File tree

29 files changed

+336
-134
lines changed

29 files changed

+336
-134
lines changed

.github/workflows/devapp1.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ name: DEVAPP1 CI
66
on:
77
# Triggers the workflow on push or approved pull request on R1-2021 branch
88
push:
9-
branches: [ Krombacher-23 ]
9+
branches: [ GnarlyPine-24 ]
1010

1111
# Allows you to run this workflow manually from the Actions tab
1212
workflow_dispatch:
@@ -32,7 +32,7 @@ jobs:
3232
script: |
3333
cd /home/upstage/upstage/ui/dashboard/
3434
git fetch
35-
git checkout Krombacher-23
35+
git checkout GnarlyPine-24
3636
git pull
3737
yarn
3838
yarn build:dev

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,19 @@ systemctl start upstage-streaming.service
103103
systemctl enable upstage-streaming.service
104104
```
105105

106+
7. Setup `Upstage Send Email Token To Cient Server`:
107+
```bash
108+
109+
# Only setup on Upstage Prod
110+
# Create the systemd service using our example configuration
111+
cp system/prod/upstage_email_token.service /etc/systemd/system/upstage_email_token.service
112+
113+
# Start the service
114+
systemctl start upstage_email_token.service
115+
116+
# Enable the service if you want it start automatically on boot
117+
systemctl enable upstage_email_token.service
118+
```
106119
## Configurations
107120

108121
UpStage was designed to have multiple instances of it working independently. Each instance could have its own configurations set to get worked.
@@ -151,6 +164,19 @@ CIPHER_KEY='' # Paste the result from fernet_crypto.py
151164
SECRET_KEY='' # Paste the result from running __init__.py
152165
```
153166

167+
```python
168+
# When setup Send Email Service, only the Upstage server has permission to send the email. The Client-server has to call the external API of the Upstage server.
169+
# Upstage server will generate and send a token to each client server every 10 minutes. That token has expired in 10 minutes. Client-server stores that token in MongoDB and uses that token to call the sendEmailExternal API of the Upstage server
170+
EMAIL_USE_TLS = True
171+
EMAIL_HOST = 'mail.gandi.net'
172+
EMAIL_HOST_USER = ''
173+
EMAIL_HOST_PASSWORD = ''
174+
EMAIL_PORT = 465
175+
ADMIN_EMAIL = '' # A list admin email always in bcc
176+
EMAIL_HOST_DISPLAY_NAME = 'UpStage Support'
177+
ACCEPT_SERVER_SEND_EMAIL_EXTERNAL = ['http://127.0.0.1:8000/'] # This is setup only in app1 server, All client server endpoint having permission using Upstage Send Email service
178+
```
179+
154180
```python
155181
# When setuping Streaming Service, a secret key is recommended so that we can set up password protection and prevent your streaming server from being used by strangers. You will need to paste that key here so that we can generate QR codes with correct stream sign, only then the players will be able to broadcast.
156182
STREAM_KEY=''

auth/auth_mutation.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ class Arguments(object):
8989

9090
message = graphene.String()
9191
username = graphene.String()
92-
93-
def mutate(self, info, username_or_email):
92+
93+
@staticmethod
94+
async def mutate(self, info, username_or_email):
9495
with ScopedSession() as local_db_session:
9596
if '@' in username_or_email:
9697
user = local_db_session.query(User).filter(
@@ -114,7 +115,7 @@ def mutate(self, info, username_or_email):
114115
local_db_session.flush()
115116
local_db_session.add(OneTimeTOTP(user_id=user.id, code=otp))
116117
local_db_session.flush()
117-
send([email], f"Password reset for account {user.username}", password_reset(user, otp))
118+
await send([email], f"Password reset for account {user.username}", password_reset(user, otp))
118119

119120
return RequestPasswordResetMutation(
120121
message=f"We've sent an email with a code to reset your password to {email}.",

auth/fernet_crypto.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ def check_password(enc_key,password):
2626
return decrypt(enc_key) == password
2727

2828
if __name__ == '__main__':
29-
print("Copy-paste this key: {}".format(Fernet.generate_key()))
29+
c = Fernet(b'Y9fzvL6bbiTqWumKfk7-phWutaPjK_HcdhIHGqQmSg0=')
30+
text=str.encode('12345678')
31+
print(c.encrypt(text).decode())
32+
# print("Copy-paste this key: {}".format(Fernet.generate_key()))

config/schema.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
# -*- coding: iso8859-15 -*-
22
from os import name
33

4-
from flask_jwt_extended.view_decorators import jwt_required
5-
from config.project_globals import DBSession, ScopedSession, app
4+
import graphene
65
from flask_graphql import GraphQLView
7-
from config.settings import NGINX_CONFIG_FILE, URL_PREFIX
6+
from flask_jwt_extended.view_decorators import jwt_required
87
from graphene import relay
9-
import graphene
10-
from config.models import Config as ConfigModel
8+
from graphql.execution.executors.asyncio import AsyncioExecutor
119
from mail.mail_utils import send
1210
from user.models import ADMIN, SUPER_ADMIN
1311
from user.user_utils import current_user
1412

13+
from config.models import Config as ConfigModel
14+
from config.project_globals import DBSession, ScopedSession, app
15+
from config.settings import NGINX_CONFIG_FILE, URL_PREFIX
16+
1517
TERMS_OF_SERVICE = 'TERMS_OF_SERVICE'
1618
MANUAL = 'MANUAL'
1719
EMAIL_SUBJECT_PREFIX = 'EMAIL_SUBJECT_PREFIX'
20+
ENABLE_DONATE = 'ENABLE_DONATE'
1821

1922

2023
class NginxConfig(graphene.ObjectType):
@@ -46,6 +49,7 @@ class SystemConfig(graphene.ObjectType):
4649
termsOfService = graphene.String()
4750
manual = graphene.String()
4851
esp = graphene.String()
52+
enableDonate = graphene.Boolean()
4953

5054
def resolve_termsOfService(self, info):
5155
return get_config(TERMS_OF_SERVICE)
@@ -56,6 +60,9 @@ def resolve_manual(self, info):
5660
def resolve_esp(self, info):
5761
return get_config(EMAIL_SUBJECT_PREFIX)
5862

63+
def resolve_enableDonate(self, info):
64+
return get_config(ENABLE_DONATE)
65+
5966
class FoyerConfig(graphene.ObjectType):
6067
title = graphene.String()
6168
description = graphene.String()
@@ -74,6 +81,7 @@ def resolve_menu(self, info):
7481
def resolve_showRegistration(self, info):
7582
return get_config('SHOW_REGISTRATION')
7683

84+
7785
class Query(graphene.ObjectType):
7886
node = relay.Node.Field()
7987
nginx = graphene.Field(NginxConfig)
@@ -158,13 +166,13 @@ class Arguments:
158166
required=False, description="The bcc recipients of the email. Comma separated.")
159167

160168
@jwt_required()
161-
def mutate(self, info, subject, body, recipients, bcc):
169+
async def mutate(self, info, subject, body, recipients, bcc):
162170
code, error, user, timezone = current_user()
163-
if not user.role in (ADMIN, SUPER_ADMIN):
171+
if not user.role in (ADMIN, SUPER_ADMIN) and not user.can_send_email:
164172
raise Exception(
165173
"Only Admin can send notification emails!")
166174

167-
send(recipients.split(','), subject, body, bcc.split(','))
175+
await send(recipients.split(','), subject, body, bcc.split(','))
168176
return SendEmail(success=True)
169177

170178

@@ -179,6 +187,6 @@ class Mutation(graphene.ObjectType):
179187
app.add_url_rule(
180188
f'/{URL_PREFIX}config_graphql/', view_func=GraphQLView.as_view(
181189
"config_graphql", schema=config_schema,
182-
graphiql=True
190+
graphiql=True, executor=AsyncioExecutor()
183191
)
184192
)

config/settings/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
EMAIL_HOST_PASSWORD = ''
3636
EMAIL_HOST_DISPLAY_NAME = ''
3737
EMAIL_TIME_TRIGGER_SECONDS = 60 * 1 # 1 minute
38+
EMAIL_TIME_EXPIRED_TOKEN = 60 * 10 # 10 minute
39+
ACCEPT_SERVER_SEND_EMAIL_EXTERNAL = ['https://dev-app1.upstage.live'] # All client server endpoints. Only config on upstage server
40+
SEND_EMAIL_SERVER = 'https://upstage.live' # Send email server endpoint
41+
ACCEPT_EMAIL_HOST = ['app1']
3842

3943
MONGO_HOST = ""
4044
MONGO_PORT = 0
@@ -49,6 +53,7 @@
4953
PERFORMANCE_TOPIC_RULE = "#"
5054

5155
MONGODB_COLLECTION_EMAIL = 'EMAIL_OUTBOUND_QUEUE'
56+
MONGODB_COLLECTION_TOKEN = 'EMAIL_ACCEPT_TOKEN'
5257

5358
EMAIL_PORT = 587
5459
#EMAIL_PORT = 25

config/settings/your_hostname.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,13 @@
119119
SECRET_KEY='' # Paste the result from running __init__.py
120120
STREAM_KEY='' # Paste the secret key from node media server config
121121
STRIPE_KEY = ''
122-
STRIPE_PRODUCT_ID = ''
122+
STRIPE_PRODUCT_ID = ''
123+
124+
EMAIL_HOST = ''
125+
EMAIL_HOST_USER = ''
126+
EMAIL_HOST_PASSWORD = ''
127+
ADMIN_EMAIL = ''
128+
EMAIL_HOST_DISPLAY_NAME = ''
129+
ACCEPT_SERVER_SEND_EMAIL_EXTERNAL = ['https://dev-app1.upstage.live'] # All client server endpoints. Only config on upstage server
130+
SEND_EMAIL_SERVER = 'https://upstage.live' # Send email server endpoint
131+
ACCEPT_EMAIL_HOST = ['app1']

config/sqlfiles/create.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ CREATE TABLE "public"."config" (
1111
INSERT INTO "config" ("name", "value") VALUES ('FOYER_TITLE', 'CYBERFORMANCE PLATFORM');
1212
INSERT INTO "config" ("name", "value") VALUES ('FOYER_DESCRIPTION', 'UpStage is an online venue for live performance: remote performers collaborate in real time using digital media, and online audiences anywhere in the world join events by going to a web page, without having to download and install any additional software. UpStage is available free to anyone who would like to use it.');
1313
INSERT INTO "config" ("name", "value") VALUES ('FOYER_MENU', 'UpStage User Manual (https://docs.upstage.live/)
14-
Customise Foyer (/backstage/admin/foyer-customisation)');
14+
Customise Foyer (/backstage/admin/foyer-customisation)');
15+
16+
INSERT INTO "config" ("name", "value") VALUES ('ENABLE_DONATE', 'true');

event_archive/db.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import logging
2-
import secrets
32
import os
3+
import secrets
44
import sys
55

66
import pymongo
7+
from config.settings import (EMAIL_TIME_EXPIRED_TOKEN, MONGO_DB, MONGO_HOST,
8+
MONGO_PORT, MONGODB_COLLECTION_TOKEN,
9+
SQLALCHEMY_DATABASE_URI)
710
from sqlalchemy import create_engine
811
from sqlalchemy.orm import sessionmaker
912

10-
from config.settings import MONGO_HOST, MONGO_PORT, SQLALCHEMY_DATABASE_URI
11-
1213

1314
def build_mongo_client(host=MONGO_HOST, port=MONGO_PORT):
1415
return pymongo.MongoClient(host, port)
@@ -21,4 +22,18 @@ def build_pg_engine(connection_string=SQLALCHEMY_DATABASE_URI):
2122
def build_pg_session():
2223
eng = build_pg_engine()
2324
Session = sessionmaker(bind=eng)
24-
return Session()
25+
return Session()
26+
27+
28+
def get_mongo_token_collection():
29+
client = build_mongo_client()
30+
mongo_db = client[MONGO_DB]
31+
# queue = db[EVENT_COLLECTION]
32+
33+
# mongo_connection = pymongo.MongoClient(f'mongodb://{MONGO_HOST}:{MONGO_PORT}/')
34+
# mongo_db = mongo_connection[MONGO_DB]
35+
collection = mongo_db[MONGODB_COLLECTION_TOKEN]
36+
if 'expired_date' in collection.index_information():
37+
collection.drop_index('expired_date')
38+
collection.create_index("expired_date", name="expired_date", expireAfterSeconds=EMAIL_TIME_EXPIRED_TOKEN)
39+
return collection

0 commit comments

Comments
 (0)