多租户更改

This commit is contained in:
richjohnrambo
2026-08-11 15:59:57 +08:00
parent 6c800de67d
commit c2076721fc
453 changed files with 102349 additions and 47 deletions
+12
View File
@@ -0,0 +1,12 @@
# Example of a REST authenticator server.
This is an example of a server-side [REST authenticator](../server/auth/rest/). It's a basic Python script meant to be run as a web server. It implements the required endpoints. It responds to all requests with dummy data.
The service uses [Flask](http://flask.pocoo.org/), so make sure it's installed:
```
pip install flask
```
Run the service as
```
python auth.py
```
Regular → Executable
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/python
# Sample Tinode REST/JSON-RPC authentication service.
# See https://github.com/tinode/chat/rest-auth for details.
from flask import Flask, jsonify, make_response, request
import base64
import json
dummy_data = {}
app = Flask(__name__)
def parse_secret(ecoded_secret):
secret = base64.b64decode(ecoded_secret)
return secret.split(':')
@app.route('/')
def index():
return 'Sample Tinode REST/JSON-RPC authentication service. '+\
'See <a href="https://github.com/tinode/chat/rest-auth/">https://github.com/tinode/chat/rest-auth/</a> for details.'
@app.route('/add', methods=['POST'])
def add():
return jsonify({'err': 'unsupported'})
@app.route('/auth', methods=['POST'])
def auth():
if not request.json:
return jsonify({'err': 'malformed'})
uname, password = parse_secret(request.json.get('secret'))
if uname in dummy_data:
if dummy_data[uname]['password'] != password:
# Wrong password
return jsonify({'err': 'failed'})
if 'uid' in dummy_data[uname]:
# We have uname -> uid mapping
return jsonify({
'rec': {
'uid': dummy_data[uname]['uid'],
'authlvl': dummy_data[uname]['authlvl'],
'features': dummy_data[uname]['features']
}
})
else:
# This is the first login. Tell Tinode to create a new account.
return jsonify({
'rec': {
'authlvl': dummy_data[uname]['authlvl'],
'tags': dummy_data[uname]['tags'],
'features': dummy_data[uname]['features']
},
'newacc': {
'auth': dummy_data[uname]['auth'],
'anon': dummy_data[uname]['anon'],
'public': dummy_data[uname]['public'],
'private': dummy_data[uname]['private']
}
})
return jsonify({'err': 'unsupported'})
else:
return jsonify({'err': 'not found'})
@app.route('/checkunique', methods=['POST'])
def checkunique():
return jsonify({'err': 'unsupported'})
@app.route('/del', methods=['POST'])
def xdel():
return jsonify({'err': 'unsupported'})
@app.route('/gen', methods=['POST'])
def gen():
return jsonify({'err': 'unsupported'})
@app.route('/link', methods=['POST'])
def link():
if not request.json:
return jsonify({'err': 'malformed'})
rec = request.json.get('rec', None)
secret = request.json.get('secret', '')
if not rec or not rec['uid'] or not secret:
return jsonify({'err': 'malformed'})
# Save the link account <-> secret to database.
uname, password = parse_secret(secret)
if uname not in dummy_data:
# Unknown user name
return jsonify({'err': 'not found'})
if 'uid' in dummy_data[uname]:
# Already linked
return jsonify({'err': 'duplicate value'})
# Save updated data to file
dummy_data[uname]['uid'] = rec['uid']
with open('dummy_data.json', 'w') as outfile:
json.dump(dummy_data, outfile, indent=2, sort_keys=True)
# Success
return jsonify({})
@app.route('/upd', methods=['POST'])
def upd():
return jsonify({'err': 'unsupported'})
@app.route('/rtagns', methods=['POST'])
def rtags():
# Return dummy namespace "rest" and "email", let client check logins by regular expression.
return jsonify({'strarr': ['rest', 'email'], 'byteval': base64.b64encode('^[a-z0-9_]{3,8}$')})
@app.errorhandler(404)
def not_found(error):
return make_response(jsonify({'err': 'not found'}), 404)
@app.errorhandler(405)
def not_found(error):
return make_response(jsonify({'err': 'method not allowed'}), 405)
if __name__ == '__main__':
# Load previously saved dummy data. Dummy data contains
# tinode user id <-> user name mapping and data for account creation.
with open('dummy_data.json') as infile:
dummy_data = json.load(infile)
app.run(debug=True)
+128
View File
@@ -0,0 +1,128 @@
{
"alice": {
"anon": "N",
"auth": "JRWPA",
"authlvl": "auth",
"features": "V",
"password": "alice123",
"private": "email:bob@example.com,email:carol@example.com,email:dave@example.com,email:eve@example.com,email:frank@example.com",
"public": {
"fn": "Alice Johnson",
"photo": {
"data": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAQUGAwQI/8QAKRAAAgEDAgQFBQAAAAAAAAAAAQIDAAQRBTEGIUFREhMUYYEiQnGCo//EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/EAB4RAAICAgMBAQAAAAAAAAAAAAECABEDIRNB4YGR/9oADAMBAAIRAxEAPwD1TQ5YoZ5ikvFNzJBpywWsvl3d3ItvEw3Utuw91UM361CaFzSKXYKO475GjSLhS9kvdKX1bq95bs1vO22XQ4Jx0zgN+CKd53oDYuHQoxU9QNvjoaj9Tj1DU+MFGny28cOlw/U00RkBmk7AMMFUH9asCcVhDDFG80kcaI0z+Nyox4jgLk9zgAfAoy3qbxZeMlgN1X75cl9GF7pXFdxbahJbyDU4/URtDEY18yMBXGCx5lSh3+01Y965praKWeCWREaSFiY2ZQSpIwSD05Ej5rUNge+9FFakzZeQhq3W/nlT/9k=",
"type": "jpeg"
}
},
"tags": [
"email:alice@example.com"
]
},
"bob": {
"anon": "N",
"auth": "JRWPA",
"authlvl": "auth",
"features": "V",
"password": "bob123",
"private": "email:alice@example.com,email:carol@example.com,email:dave@example.com,email:eve@example.com,email:frank@example.com",
"public": {
"fn": "Bob Smith",
"photo": {
"data": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGgABAAEFAAAAAAAAAAAAAAAABQMAAQIECP/EACkQAAEDAgQFBAMAAAAAAAAAAAECAwQAEQUSITETIjJBgUJRUnFhofD/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAgED/8QAHxEAAQUBAAIDAAAAAAAAAAAAEQABAgMSMXGhE2Hw/9oADAMBAAIRAxEAPwDqisb+4FWvv4obFC65i8RlD7rLamXVnIQLkKQBuPyaicsMQudk8RIPPacBvtVeKEw5x5M5yOp9choNhZUoDMg32JAA286U3SE9MUrntiFHbTXqIoTForMrHYKJLaFpDDx5hf1N07/CtSbAizVIMuOy8UdPEQFW+r1lsNsPCm2v5IZB536dFxG2oWLJjYblDRbUp1pJ5UG4ym3Ym6vvxT99NRUEWMxFa4cdpDSPigAD9VOe9zSuGGH5kprww9NxvC//2Q==",
"type": "jpeg"
}
},
"tags": [
"email:bob@example.com"
]
},
"carol": {
"anon": "N",
"auth": "JRWPA",
"authlvl": "auth",
"features": "V",
"password": "carol123",
"private": "email:alice@example.com,email:bob@example.com,email:dave@example.com,email:eve@example.com,email:frank@example.com",
"public": {
"fn": "Carol Xmas",
"photo": {
"data": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAQUGBAMI/8QAJRAAAQQCAQMEAwAAAAAAAAAAAQIDBAUAERITIVEGMUFxFCJh/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQL/xAAdEQEAAgEFAQAAAAAAAAAAAAABABECAxIhMcFB/9oADAMBAAIRAxEAPwD1RrAO31hyPkuzL71JPr4816DXVnBEhUfiHXnlpC+HIg8UhBSTrSiVDuAP2cNPdfNBywWpYYcU1Ncuv6iVWE2WlWilMlSVdP6ISD3/AKT7feNsEBobjB8ZH0zyK71vfwJJ6blk43YRSo9nQGW2VpT5KS0CR4cTlhmC0qoFqwGbKHGlsg8g2+0HEg+dH5ysMjGx6SvfIJNgcSVFOxyA2RnTFlVS1tQlxNVXxIYcIK/x2Q3y17b0O+M8lr51Gf/Z",
"type": "jpeg"
}
},
"tags": [
"email:carol@example.com"
]
},
"dave": {
"anon": "N",
"auth": "JRWPA",
"authlvl": "auth",
"features": "V",
"password": "dave123",
"private": "email:alice@example.com,email:bob@example.com,email:carol@example.com,email:eve@example.com,email:frank@example.com",
"public": {
"fn": "Dave Goliathsson",
"photo": {
"data": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGQAAAwADAAAAAAAAAAAAAAAAAAQFAgMI/8QAIxAAAgIBAwQDAQAAAAAAAAAAAQIAAxEEITEFEhNBYXOxof/EABcBAQEBAQAAAAAAAAAAAAAAAAECAAP/xAAcEQACAwADAQAAAAAAAAAAAAABAgADERIxwUH/2gAMAwEAAhEDEQA/AOqMQ9wkxksu6lfX57URKkICEcktn18CcbH45g3YgSpCT6bbKtSlF9nkDglHIwduQcbShKRwwhCIVbdX1X01frx6LXaPTXv33UVWPjGXQE4kWKzYV+Hwj2Ii5ZdT1GrxN3JSGLMOMnYD9/kozBFWtQqAADgATZGusrpPZmM//9k=",
"type": "jpeg"
}
},
"tags": [
"email:dave@example.com"
]
},
"eve": {
"anon": "N",
"auth": "JRWPA",
"authlvl": "auth",
"features": "V",
"password": "eve123",
"private": "email:alice@example.com,email:bob@example.com,email:carol@example.com,email:dave@example.com,email:frank@example.com",
"public": {
"fn": "Eve Adams",
"photo": {
"data": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAQUGAgQI/8QAIxAAAQQCAAcBAQAAAAAAAAAAAgEDBAUAEQYSEyExYXFBkf/EABUBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGxEAAwEBAQEBAAAAAAAAAAAAAQIRABIhA3H/2gAMAwEAAhEDEQA/APVKZlfiZrymSt6EiVxJAhtzpMZgor7pIwSIpEJtIm9ov4RYkXozJE6Ms1R81h/MV1dYcIjIp8yTzJrT5oqD80iY0yEAHzRgAfDcFyUv4EWfxhVtzY7MhsYMgkF0EJEXqM9++VZeMXWVRXWhtLZQIkvp7QFfZFzl351tO3hP5iRuTcvk/DXGtqYFdzrXw2I5Hrm6QIO9eN6zvL1rF1dS1taZnXwIcUyTREwyLaqnvSYyX3kJptuLmm2/u//Z",
"type": "jpeg"
}
},
"tags": [
"email:eve@example.com"
]
},
"frank": {
"anon": "N",
"auth": "JRWPA",
"authlvl": "auth",
"features": "V",
"password": "frank123",
"private": "email:alice@example.com,email:bob@example.com,email:carol@example.com,email:dave@example.com,email:eve@example.com",
"public": {
"fn": "Frank Singer",
"photo": {
"data": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAUCAwQI/8QAJxAAAQQBAgUEAwAAAAAAAAAAAQACAwQREjEFEyFBgQYUU2FxcpH/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAHBEBAAMBAQADAAAAAAAAAAAAAQACEQMSUaHh/9oADAMBAAIRAxEAPwDqfHQoIwcdkZ3SXibZZeMVK0diaKJ0ErzyyBkh0YHb7KYazPpfxXc39joeFJYaVR9bUXWZ5tXyuBx+MBbUMdVTUyBCQ8TrR2vUNBkzGvb7aY4P7RJ605VLomGZspa3WGlodjqAdxnwP4nVx2T15nSvl+T6ZCpSgqauRG1mrfHdat0I8qV2XWpUwJ//2Q==",
"type": "jpeg"
}
},
"tags": [
"email:frank@example.com"
]
},
"xena": {
"anon": "N",
"auth": "JRWPA",
"authlvl": "root",
"features": "V",
"password": "xena123",
"private": "",
"public": {
"fn": "Xena Peaceful Peasant",
"photo": {
"data": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAABgAEBQj/xAArEAABAwMCBAQHAAAAAAAAAAABAgMEAAUREjEGISJhNEFRcRQjJTJCQ4L/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A9U1VUeukuRar/EffcUu1TMRVg7R3s/LX7LzoPfR6mgQ1Ue4fmSbvOl3FLhTavDxG88ncHre9ieSeyc/lyQ0FRTi36y43ww2fGtlyaobtRQcHHopZ6R/RH20rrM1GYakOvtstIfeADiwkBS8bZPnjJoOBwbIcYadsM7R8baghoEJwHmP1OgbcwMEDZST5YpRWZUZgy0yiy2ZSUFsO6RqCSQSnO+MgHHatNB//2Q==",
"type": "jpeg"
}
},
"tags": [
"email:xena@example.com"
]
}
}
+1
View File
@@ -0,0 +1 @@
flask>=1.1.0