mirror of https://gitlab.com/litecord/litecord.git
admin_api.instance_invites add impls for other endpoints
- docs/admin_api.md: document them - docs/admin_api.md: add basic usage of the api
This commit is contained in:
parent
5fb27c04a2
commit
78aba9432e
|
|
@ -1,6 +1,13 @@
|
||||||
# Litecord Admin API
|
# Litecord Admin API
|
||||||
|
|
||||||
the base path is `/api/v6/admin`.
|
Litecord's Admin API uses the same authentication methods as Discord,
|
||||||
|
it's the same `Authorization` header, and the same token.
|
||||||
|
|
||||||
|
Only users who have the staff flag set can use the Admin API. Instance
|
||||||
|
owners can use the `./manage.py make_staff` manage task to set someone
|
||||||
|
as a staff user, granting them access over the administration functions.
|
||||||
|
|
||||||
|
The base path is `/api/v6/admin`.
|
||||||
|
|
||||||
## User management
|
## User management
|
||||||
|
|
||||||
|
|
@ -27,17 +34,36 @@ Search users.
|
||||||
|
|
||||||
## Instance invites
|
## Instance invites
|
||||||
|
|
||||||
|
Instance invites are used for instances that do not have open
|
||||||
|
registrations but want to let some people in regardless. Users
|
||||||
|
go to the `/invite_register.html` page in the instance and put
|
||||||
|
their data in.
|
||||||
|
|
||||||
|
### Instance Invite object
|
||||||
|
|
||||||
|
| field | type | description |
|
||||||
|
| --: | :-- | :-- |
|
||||||
|
| code | string | instance invite code |
|
||||||
|
| created\_at | ISO8907 timestamp | when the invite was created |
|
||||||
|
| max\_uses | integer | maximum amount of uses |
|
||||||
|
| uses | integer | how many times has the invite been used |
|
||||||
|
|
||||||
### `GET /instance/invites`
|
### `GET /instance/invites`
|
||||||
|
|
||||||
**TODO**
|
Get a list of instance invites.
|
||||||
|
|
||||||
### `PUT /instance/invites`
|
### `PUT /instance/invites`
|
||||||
|
|
||||||
**TODO**
|
Create an instance invite. Receives only the `max_uses`
|
||||||
|
field from the instance invites object. Returns a full
|
||||||
|
instance invite object.
|
||||||
|
|
||||||
### `DELETE /instance/invites/<invite>`
|
### `DELETE /instance/invites/<invite>`
|
||||||
|
|
||||||
**TODO**
|
Delete an invite. Does not have any input, only the instance invite's `code`
|
||||||
|
as the `<invite>` parameter in the URL.
|
||||||
|
|
||||||
|
Returns empty body 204 on success, 404 on invite not found.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,3 +46,7 @@ USER_CREATE = {
|
||||||
'email': {'type': 'email', 'required': True},
|
'email': {'type': 'email', 'required': True},
|
||||||
'password': {'type': 'string', 'minlength': 5, 'required': True},
|
'password': {'type': 'string', 'minlength': 5, 'required': True},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INSTANCE_INVITE = {
|
||||||
|
'max_uses': {'type': 'integer', 'required': True}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,40 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from quart import Blueprint, jsonify, current_app as app
|
import string
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
from quart import Blueprint, jsonify, current_app as app, request
|
||||||
|
|
||||||
from litecord.auth import admin_check
|
from litecord.auth import admin_check
|
||||||
|
from litecord.types import timestamp_
|
||||||
|
from litecord.schemas import validate
|
||||||
|
from litecord.admin_schemas import INSTANCE_INVITE
|
||||||
|
|
||||||
bp = Blueprint('instance_invites', __name__)
|
bp = Blueprint('instance_invites', __name__)
|
||||||
|
ALPHABET = string.ascii_lowercase + string.ascii_uppercase + string.digits
|
||||||
|
|
||||||
|
|
||||||
|
async def _gen_inv() -> str:
|
||||||
|
"""Generate an invite code"""
|
||||||
|
return ''.join(choice(ALPHABET) for _ in range(6))
|
||||||
|
|
||||||
|
|
||||||
|
async def gen_inv(ctx) -> str:
|
||||||
|
"""Generate an invite."""
|
||||||
|
for _ in range(10):
|
||||||
|
possible_inv = await _gen_inv()
|
||||||
|
|
||||||
|
created_at = await ctx.db.fetchval("""
|
||||||
|
SELECT created_at
|
||||||
|
FROM instance_invites
|
||||||
|
WHERE code = $1
|
||||||
|
""", possible_inv)
|
||||||
|
|
||||||
|
if created_at is None:
|
||||||
|
return possible_inv
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@bp.route('', methods=['GET'])
|
@bp.route('', methods=['GET'])
|
||||||
|
|
@ -33,4 +62,48 @@ async def _all_instance_invites():
|
||||||
FROM instance_invites
|
FROM instance_invites
|
||||||
""")
|
""")
|
||||||
|
|
||||||
return jsonify([dict(row) for row in rows])
|
rows = [dict(row) for row in rows]
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
row['timestamp'] = timestamp_(row['timestamp'])
|
||||||
|
|
||||||
|
return jsonify(rows)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('', methods=['PUT'])
|
||||||
|
async def _create_invite():
|
||||||
|
await admin_check()
|
||||||
|
|
||||||
|
code = await gen_inv(app)
|
||||||
|
if not code:
|
||||||
|
return 'failed to make invite', 500
|
||||||
|
|
||||||
|
j = validate(await request.get_json(), INSTANCE_INVITE)
|
||||||
|
|
||||||
|
await app.db.execute("""
|
||||||
|
INSERT INTO instance_invites (code, max_uses)
|
||||||
|
VALUES ($1, $2)
|
||||||
|
""", code, j['max_uses'])
|
||||||
|
|
||||||
|
inv = dict(await app.db.fetchrow("""
|
||||||
|
SELECT code, created_at, uses, max_uses
|
||||||
|
FROM instance_invites
|
||||||
|
WHERE code = $1
|
||||||
|
""", code))
|
||||||
|
|
||||||
|
return jsonify(dict(inv))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/<invite>', methods=['DELETE'])
|
||||||
|
async def _del_invite(invite: str):
|
||||||
|
await admin_check()
|
||||||
|
|
||||||
|
res = await app.db.execute("""
|
||||||
|
DELETE FROM instance_invites
|
||||||
|
WHERE code = $1
|
||||||
|
""", invite)
|
||||||
|
|
||||||
|
if res.lower() == 'update 0':
|
||||||
|
return 'invite not found', 404
|
||||||
|
|
||||||
|
return '', 204
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue