Skip to content

Commit

Permalink
Merge pull request #43 from nanocom2024/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
hyouhyan committed Sep 15, 2024
2 parents 0597b95 + 6e6ee71 commit 70e6132
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 103 deletions.
3 changes: 2 additions & 1 deletion server/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
PATH_TO_FIREBASE_JSON = "example"
JWT_SECRET_KEY = "example"
FIREBASE_API_KEY = "example"
FIREBASE_API_KEY = "example"
LOG_WEBHOOK_URL = "https://discord.com/api/webhooks/1234567890/EXAMPLE"
11 changes: 6 additions & 5 deletions server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ FirebaseのAuthenticationを用いています
PATH_TO_FIREBASE_JSON = "example"
JWT_SECRET_KEY = "example"
FIREBASE_API_KEY = "example"
LOG_WEBHOOK_URL = "https://discord.com/api/webhooks/EXAMPLE"
```

Firebase Authenticationに従ってsdkのjsonを配置して,パスを設定してください

・serverの秘密鍵の設定もしてください

・firebaseのAPIキーも設定してください
- Firebase Authenticationに従ってsdkのjsonを配置して,パスを設定してください
- serverの秘密鍵の設定もしてください
- firebaseのAPIキーも設定してください
- ログをdiscordに送信する場合はwebhookのURLを設定してください
- 指定なしの場合,Webhook機能は自動的に無効になります

### ライブラリのインストール

Expand Down
1 change: 1 addition & 0 deletions server/src/Auth/firebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
def sign_in_with_email_and_password(api_key, email, password):
"""
Firebaseで認証を行う(SDKの signInWithEmailAndPassword と同値)
:param api_key:
:param email:
:param password:
Expand Down
12 changes: 8 additions & 4 deletions server/src/Auth/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ def signup():
if not password:
return jsonify({'error': 'Missing password'}), 400

if users.find_one({'email': email}):
return jsonify({'error': 'The user with the provided email already exists (EMAIL_EXISTS).'}), 400

try:
user = auth.create_user(email=email, password=password)
access_token = create_access_token(identity=user.uid)
except Exception as e:
return jsonify({'error': str(e)}), 400

if users.find_one({'email': email}):
users.delete_many({'email': email})

user = {
'uid': user.uid,
'name': name,
Expand Down Expand Up @@ -74,7 +74,11 @@ def signin():
if 'error' in res:
return jsonify({'error': res['error']['message']}), 400

users.update_one({'email': email}, {'$set': {'token': res['idToken']}})
if not users.find({'email': email}):
# firebaseにuserが存在するが、DBには存在しない場合
return jsonify({'error': 'User not found'}), 400
else:
users.update_one({'email': email}, {'$set': {'token': res['idToken']}})

return jsonify({'token': res['idToken']}), 200

Expand Down
44 changes: 44 additions & 0 deletions server/src/Pairing/PairingModel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import hashlib
from DB import DB

db = DB()
device_keys = db.device_keys


def generate_major_minor(public_key):
"""
majorとminorをpublic_keyから生成する
:param public_key: str
:return major, minor: (str, str)
"""

temp = public_key
while True:
major, minor = generate(temp)
device_key = device_keys.find_one({'major': major, 'minor': minor})
if not device_key:
break
temp = hashlib.sha256(temp.encode()).hexdigest()

return str(major), str(minor)


def generate(key):
forward = key[:32]
backward = key[32:]

forward_hash = hashlib.sha256(forward.encode()).hexdigest()
backward_hash = hashlib.sha256(backward.encode()).hexdigest()

# 16bitのuintに変換
major = int(forward_hash, 16) % 2**16
minor = int(backward_hash, 16) % 2**16

return major, minor


if __name__ == '__main__':
public_key = 'a' * 64
print(generate(public_key))
# (42311, 42311)
37 changes: 26 additions & 11 deletions server/src/Pairing/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from flask import Blueprint, request, jsonify
from DB import DB
from crypto.generate import generate_ed25519_keypair
from Pairing import PairingModel
from flask_jwt_extended import create_access_token

PAIRING_BP = Blueprint('pairing', __name__, url_prefix='/pairing')
Expand All @@ -13,8 +14,8 @@
pairings = db.pairings


@PAIRING_BP.route('/generate_device_key', methods=['POST'])
def generate_device_key():
@PAIRING_BP.route('/generate_major_minor', methods=['POST'])
def generate_major_minor():
uid = request.json['uid']
if not uid:
return jsonify({'error': 'Missing uid'}), 400
Expand All @@ -24,40 +25,54 @@ def generate_device_key():

private_key, public_key = generate_ed25519_keypair()

major, minor = PairingModel.generate_major_minor(public_key)

device_keys.insert_one({
'uid': uid,
'private_key': private_key,
'public_key': public_key
'public_key': public_key,
'major': major,
'minor': minor
})

return jsonify({'private_key': private_key, 'public_key': public_key}), 200
return jsonify({
'private_key': private_key,
'public_key': public_key,
'major': major,
'minor': minor
}), 200


@PAIRING_BP.route('/register_pairing', methods=['POST'])
def register_pairing():
token = request.json['token']
if not token:
return jsonify({'error': 'Missing token'}), 400
public_key = request.json['public_key']
if not public_key:
return jsonify({'error': 'Missing public_key'}), 400
major = request.json['major']
if not major:
return jsonify({'error': 'Missing major'}), 400
minor = request.json['minor']
if not minor:
return jsonify({'error': 'Missing minor'}), 400

user = users.find_one({'token': token})
if not user:
return jsonify({'error': 'Invalid token'}), 400

device_key = device_keys.find_one({'public_key': public_key})
device_key = device_keys.find_one({'major': major, 'minor': minor})
if not device_key:
return jsonify({'error': 'Invalid public_key'}), 400
return jsonify({'error': 'Invalid major,minor'}), 400

pairings.delete_many({'uid': user['uid']})
pairings.delete_many({'public_key': device_key['public_key']})
pairings.delete_many({'private_key': device_key['private_key']})

pairings.insert_one({
'uid': user['uid'],
'private_key': device_key['private_key'],
'public_key': device_key['public_key'],
'private_key': device_key['private_key']
'major': major,
'minor': minor
})

return jsonify({'done': 'pairing'}), 200
Expand All @@ -71,7 +86,7 @@ def auth_check():

user = users.find_one({'token': token})
if not user:
return jsonify({'error': 'Invalid token'}), 400
return jsonify({'error': 'Invalid token'}), 401

new_token = create_access_token(identity=user['token'])
users.update_one({'token': token}, {'$set': {'token': new_token}})
Expand Down
30 changes: 19 additions & 11 deletions server/src/StreetPass/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

# MongoDBに接続
db = DB()
users = db.users
pairings = db.pairings
pre_passes = db.pre_passes
now_passes = db.now_passes
Expand All @@ -15,19 +16,26 @@

@STREETPASS_BP.route('/received_beacon', methods=['POST'])
def received_beacon():
received_public_key = request.json['received_public_key']
if not received_public_key:
return jsonify({'error': 'Missing received_public_key'}), 400
private_key = request.json['private_key']
if not private_key:
return jsonify({'error': 'Missing private_key'}), 400

received_user = pairings.find_one({'public_key': received_public_key})
received_major = request.json['received_major']
if not received_major:
return jsonify({'error': 'Missing received_major'}), 400
received_minor = request.json['received_minor']
if not received_minor:
return jsonify({'error': 'Missing received_minor'}), 400
token = request.json['token']
if not token:
return jsonify({'error': 'Missing token'}), 400

received_user = pairings.find_one(
{'major': received_major, 'minor': received_minor})
if not received_user:
return jsonify({'error': 'Invalid received_public_key'}), 400
sent_user = pairings.find_one({'private_key': private_key})
return jsonify({'error': 'Invalid received_major_minor'}), 400
sent_user = users.find_one({'token': token})
if not sent_user:
return jsonify({'error': 'Invalid private_key'}), 400
return jsonify({'error': 'Invalid token'}), 400

if received_user['uid'] == sent_user['uid']:
return jsonify({'pass': 'own'}), 200

threshold = datetime.datetime.now() - datetime.timedelta(seconds=30)
pre_passes.delete_many({'created_at': {'$lt': threshold}})
Expand Down
17 changes: 17 additions & 0 deletions server/src/init_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from firebase_admin import auth
from DB import DB

db = DB()
users = db.users


def db_init():
# ユーザーがDBに存在して,Firebaseに存在しない場合はDBから削除
firebase_users = auth.list_users()
db_users = users.find()

firebase_uids = [user.uid for user in firebase_users.users]

for db_user in db_users:
if db_user['uid'] not in firebase_uids:
users.delete_one({'uid': db_user['uid']})
11 changes: 6 additions & 5 deletions server/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
from Pairing.routes import PAIRING_BP
from StreetPass.routes import STREETPASS_BP
from Notification.routes import NOTIFICATION_BP
import init_server

import logging
import logging.handlers
from handlers import DiscordHandler


Expand All @@ -32,26 +32,27 @@
# jwt manager
jwt = JWTManager(app)

# init server
init_server.db_init()

# Blueprint
app.register_blueprint(AUTH_BP)
app.register_blueprint(PAIRING_BP)
app.register_blueprint(STREETPASS_BP)
app.register_blueprint(NOTIFICATION_BP)

webhook_url=settings.log_webhook_url
webhook_url = settings.log_webhook_url

# Discord Handler の作成
if(webhook_url):
if (webhook_url):
discord_handler = DiscordHandler(webhook_url)
discord_handler.setLevel(logging.INFO)
werkzeug_logger = logging.getLogger('werkzeug')
werkzeug_logger.addHandler(discord_handler)

console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
werkzeug_logger.addHandler(console_handler)



if __name__ == '__main__':
Expand Down
Loading

0 comments on commit 70e6132

Please sign in to comment.