mirror of
https://git.pleroma.social/pleroma/relay.git
synced 2024-11-12 18:58:00 +00:00
add user management api endpoints and allow cookie for api auth
This commit is contained in:
parent
08f4f0e72d
commit
1ffc609058
|
@ -13,6 +13,10 @@ schemes:
|
|||
- https
|
||||
|
||||
securityDefinitions:
|
||||
Cookie:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: user-token
|
||||
Bearer:
|
||||
type: apiKey
|
||||
name: Authorization
|
||||
|
@ -549,6 +553,104 @@ paths:
|
|||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
|
||||
/v1/user:
|
||||
get:
|
||||
tags:
|
||||
- User
|
||||
description: Get a list of all local users
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: List of users
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/User"
|
||||
|
||||
post:
|
||||
tags:
|
||||
- User
|
||||
description: Create a new user
|
||||
parameters:
|
||||
- in: formData
|
||||
name: username
|
||||
required: true
|
||||
type: string
|
||||
- in: formData
|
||||
name: password
|
||||
required: true
|
||||
type: string
|
||||
format: password
|
||||
- in: formData
|
||||
name: handle
|
||||
required: false
|
||||
type: string
|
||||
format: email
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Newly created user
|
||||
schema:
|
||||
$ref: "#/definitions/User"
|
||||
"404":
|
||||
description: User already exists
|
||||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
|
||||
patch:
|
||||
tags:
|
||||
- User
|
||||
description: Update a user's password or handle
|
||||
parameters:
|
||||
- in: formData
|
||||
name: username
|
||||
required: true
|
||||
type: string
|
||||
- in: formData
|
||||
name: password
|
||||
required: false
|
||||
type: string
|
||||
format: password
|
||||
- in: formData
|
||||
name: handle
|
||||
required: false
|
||||
type: string
|
||||
format: email
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Updated user data
|
||||
schema:
|
||||
$ref: "#/definitions/User"
|
||||
"404":
|
||||
description: User does not exist
|
||||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- User
|
||||
description: Delete a user
|
||||
parameters:
|
||||
- in: formData
|
||||
name: username
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"202":
|
||||
description: Successfully deleted user
|
||||
schema:
|
||||
$ref: "#/definitions/Message"
|
||||
"404":
|
||||
description: User not found
|
||||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
|
||||
/v1/whitelist:
|
||||
get:
|
||||
tags:
|
||||
|
@ -748,6 +850,21 @@ definitions:
|
|||
description: Character string used for authenticating with the api
|
||||
type: string
|
||||
|
||||
User:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
description: Username of the account
|
||||
type: string
|
||||
handle:
|
||||
description: Fediverse handle associated with the account
|
||||
type: string
|
||||
format: email
|
||||
created:
|
||||
description: Date the account was created
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
Whitelist:
|
||||
type: object
|
||||
properties:
|
||||
|
|
|
@ -190,13 +190,28 @@ class Connection(SqlConnection):
|
|||
return cur.one() # type: ignore
|
||||
|
||||
|
||||
def put_user(self, username: str, password: str, handle: str | None = None) -> Row:
|
||||
data = {
|
||||
'username': username,
|
||||
'hash': self.hasher.hash(password),
|
||||
'handle': handle,
|
||||
'created': datetime.now(tz = timezone.utc)
|
||||
}
|
||||
def put_user(self, username: str, password: str | None, handle: str | None = None) -> Row:
|
||||
if self.get_user(username):
|
||||
data = {
|
||||
'username': username
|
||||
}
|
||||
|
||||
if password:
|
||||
data['password'] = password
|
||||
|
||||
if handle:
|
||||
data['handler'] = handle
|
||||
|
||||
else:
|
||||
if password is None:
|
||||
raise ValueError('Password cannot be empty')
|
||||
|
||||
data = {
|
||||
'username': username,
|
||||
'hash': self.hasher.hash(password),
|
||||
'handle': handle,
|
||||
'created': datetime.now(tz = timezone.utc)
|
||||
}
|
||||
|
||||
with self.run('put-user', data) as cur:
|
||||
return cur.one() # type: ignore
|
||||
|
|
|
@ -34,7 +34,11 @@ def check_api_path(method: str, path: str) -> bool:
|
|||
@web.middleware
|
||||
async def handle_api_path(request: Request, handler: Callable) -> Response:
|
||||
try:
|
||||
request['token'] = request.headers['Authorization'].replace('Bearer', '').strip()
|
||||
if (token := request.cookies.get('user-token')):
|
||||
request['token'] = token
|
||||
|
||||
else:
|
||||
request['token'] = request.headers['Authorization'].replace('Bearer', '').strip()
|
||||
|
||||
with get_app().database.session() as conn:
|
||||
request['user'] = conn.get_user_by_token(request['token'])
|
||||
|
@ -384,6 +388,63 @@ class SoftwareBan(View):
|
|||
return Response.new({'message': 'Unbanned software'}, ctype = 'json')
|
||||
|
||||
|
||||
@register_route('/api/v1/user')
|
||||
class User(View):
|
||||
async def get(self, request: Request) -> Response:
|
||||
with self.database.session() as conn:
|
||||
items = []
|
||||
|
||||
for row in conn.execute('SELECT * FROM users'):
|
||||
del row['hash']
|
||||
items.append(row)
|
||||
|
||||
return Response.new(items, ctype = 'json')
|
||||
|
||||
|
||||
async def post(self, request: Request) -> Response:
|
||||
data = await self.get_api_data(['username', 'password'], ['handle'])
|
||||
|
||||
if isinstance(data, Response):
|
||||
return data
|
||||
|
||||
with self.database.session() as conn:
|
||||
if conn.get_user(data['username']):
|
||||
return Response.new_error(404, 'User already exists', 'json')
|
||||
|
||||
user = conn.put_user(**data)
|
||||
del user['hash']
|
||||
|
||||
return Response.new(user, ctype = 'json')
|
||||
|
||||
|
||||
async def patch(self, request: Request) -> Response:
|
||||
data = await self.get_api_data(['username'], ['password', ['handle']])
|
||||
|
||||
if isinstance(data, Response):
|
||||
return data
|
||||
|
||||
with self.database.session(True) as conn:
|
||||
user = conn.put_user(**data)
|
||||
del user['hash']
|
||||
|
||||
return Response.new(user, ctype = 'json')
|
||||
|
||||
|
||||
async def delete(self, request: Request) -> Response:
|
||||
data = await self.get_api_data(['username'], [])
|
||||
|
||||
if isinstance(data, Response):
|
||||
return data
|
||||
|
||||
with self.database.session(True) as conn:
|
||||
if not conn.get_user(data['username']):
|
||||
return Response.new_error(404, 'User does not exist', 'json')
|
||||
|
||||
conn.del_user(data['username'])
|
||||
|
||||
return Response.new({'message': 'Deleted user'}, ctype = 'json')
|
||||
|
||||
|
||||
@register_route('/api/v1/whitelist')
|
||||
class Whitelist(View):
|
||||
async def get(self, request: Request) -> Response:
|
||||
|
|
|
@ -126,7 +126,7 @@ class View(AbstractView):
|
|||
return Response.new_error(400, 'Invalid JSON data', 'json')
|
||||
|
||||
else:
|
||||
post_data = convert_data(await self.request.query) # type: ignore
|
||||
post_data = convert_data(self.request.query) # type: ignore
|
||||
|
||||
data = {}
|
||||
|
||||
|
|
Loading…
Reference in a new issue