mirror of
https://github.com/minetest/contentdb.git
synced 2025-03-14 14:22:30 +01:00
Add user info API
This commit is contained in:
@ -578,6 +578,16 @@ def all_deps():
|
||||
})
|
||||
|
||||
|
||||
@bp.route("/api/users/<username>/")
|
||||
@cors_allowed
|
||||
def user_view(username: str):
|
||||
user = User.query.filter_by(username=username).first()
|
||||
if user is None:
|
||||
error(404, "User not found")
|
||||
|
||||
return jsonify(user.get_dict())
|
||||
|
||||
|
||||
@bp.route("/api/users/<username>/stats/")
|
||||
@cors_allowed
|
||||
def user_stats(username: str):
|
||||
|
@ -166,7 +166,7 @@ Supported query parameters:
|
||||
* `short`: stuff needed for the Minetest client.
|
||||
|
||||
|
||||
## Releases
|
||||
### Releases
|
||||
|
||||
* GET `/api/releases/` (List)
|
||||
* Limited to 30 most recent releases.
|
||||
@ -228,7 +228,7 @@ curl -X DELETE https://content.minetest.net/api/packages/username/name/releases/
|
||||
```
|
||||
|
||||
|
||||
## Screenshots
|
||||
### Screenshots
|
||||
|
||||
* GET `/api/packages/<username>/<name>/screenshots/` (List)
|
||||
* Returns array of screenshot dictionaries with keys:
|
||||
@ -289,7 +289,7 @@ curl -X POST https://content.minetest.net/api/packages/username/name/screenshots
|
||||
```
|
||||
|
||||
|
||||
## Reviews
|
||||
### Reviews
|
||||
|
||||
* GET `/api/packages/<username>/<name>/reviews/` (List)
|
||||
* Returns array of review dictionaries with keys:
|
||||
@ -333,6 +333,36 @@ Example:
|
||||
```
|
||||
|
||||
|
||||
## Users
|
||||
|
||||
* GET `/api/users/<username>/`
|
||||
* `username`
|
||||
* `display_name`: human-readable name to be displayed in GUIs.
|
||||
* `rank`: ContentDB [rank](/help/ranks_permissions/).
|
||||
* `profile_pic_url`: URL to profile picture, or null.
|
||||
* `website_url`: URL to website, or null.
|
||||
* `donate_url`: URL to donate page, or null.
|
||||
* `connections`: object
|
||||
* `github`: GitHub username, or null.
|
||||
* `forums`: forums username, or null.
|
||||
* `links`: object
|
||||
* `api_packages`: URL to API to list this user's packages.
|
||||
* `profile`: URL to the HTML profile page.
|
||||
* GET `/api/users/<username>/stats/`
|
||||
* Returns daily stats for the user's packages, or null if there is no data.
|
||||
* Daily date is done based on the UTC timezone.
|
||||
* EXPERIMENTAL. This API may change without warning.
|
||||
* A table with the following keys:
|
||||
* `from`: start date, inclusive. Ex: 2022-10-22.
|
||||
* `end`: end date, inclusive. Ex: 2022-11-05.
|
||||
* `package_downloads`: map of package title to list of integers per day.
|
||||
* `platform_minetest`: list of integers per day.
|
||||
* `platform_other`: list of integers per day.
|
||||
* `reason_new`: list of integers per day.
|
||||
* `reason_dependency`: list of integers per day.
|
||||
* `reason_update`: list of integers per day.
|
||||
|
||||
|
||||
## Topics
|
||||
|
||||
* GET `/api/topics/` ([View](/api/topics/))
|
||||
|
@ -18,6 +18,7 @@
|
||||
import datetime
|
||||
import enum
|
||||
|
||||
from flask import url_for
|
||||
from flask_login import UserMixin
|
||||
from sqlalchemy import desc, text
|
||||
|
||||
@ -161,17 +162,17 @@ class User(db.Model, UserMixin):
|
||||
|
||||
# Content
|
||||
notifications = db.relationship("Notification", foreign_keys="Notification.user_id",
|
||||
order_by=desc(text("Notification.created_at")), back_populates="user", cascade="all, delete, delete-orphan")
|
||||
order_by=desc(text("Notification.created_at")), back_populates="user", cascade="all, delete, delete-orphan")
|
||||
caused_notifications = db.relationship("Notification", foreign_keys="Notification.causer_id",
|
||||
back_populates="causer", cascade="all, delete, delete-orphan", lazy="dynamic")
|
||||
back_populates="causer", cascade="all, delete, delete-orphan", lazy="dynamic")
|
||||
notification_preferences = db.relationship("UserNotificationPreferences", uselist=False, back_populates="user",
|
||||
cascade="all, delete, delete-orphan")
|
||||
cascade="all, delete, delete-orphan")
|
||||
|
||||
email_verifications = db.relationship("UserEmailVerification", foreign_keys="UserEmailVerification.user_id",
|
||||
back_populates="user", cascade="all, delete, delete-orphan", lazy="dynamic")
|
||||
back_populates="user", cascade="all, delete, delete-orphan", lazy="dynamic")
|
||||
|
||||
audit_log_entries = db.relationship("AuditLogEntry", foreign_keys="AuditLogEntry.causer_id", back_populates="causer",
|
||||
order_by=desc("audit_log_entry_created_at"), lazy="dynamic")
|
||||
order_by=desc("audit_log_entry_created_at"), lazy="dynamic")
|
||||
|
||||
maintained_packages = db.relationship("Package", lazy="dynamic", secondary="maintainers", order_by=db.asc("package_title"))
|
||||
|
||||
@ -185,6 +186,24 @@ class User(db.Model, UserMixin):
|
||||
|
||||
ban = db.relationship("UserBan", foreign_keys="UserBan.user_id", back_populates="user", uselist=False)
|
||||
|
||||
def get_dict(self):
|
||||
return {
|
||||
"username": self.username,
|
||||
"display_name": self.display_name,
|
||||
"rank": self.rank.name.lower(),
|
||||
"profile_pic_url": self.profile_pic,
|
||||
"website_url": self.website_url,
|
||||
"donate_url": self.donate_url,
|
||||
"connections": {
|
||||
"github": self.github_username,
|
||||
"forums": self.forums_username,
|
||||
},
|
||||
"links": {
|
||||
"api_packages": url_for("api.packages", author=self.username),
|
||||
"profile": url_for("users.profile", username=self.username),
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, username=None, active=False, email=None, password=None):
|
||||
self.username = username
|
||||
self.display_name = username
|
||||
@ -195,7 +214,7 @@ class User(db.Model, UserMixin):
|
||||
|
||||
def canAccessTodoList(self):
|
||||
return Permission.APPROVE_NEW.check(self) or \
|
||||
Permission.APPROVE_RELEASE.check(self)
|
||||
Permission.APPROVE_RELEASE.check(self)
|
||||
|
||||
def isClaimed(self):
|
||||
return self.rank.atLeast(UserRank.NEW_MEMBER)
|
||||
@ -272,7 +291,7 @@ class User(db.Model, UserMixin):
|
||||
|
||||
hour_ago = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
|
||||
return Thread.query.filter_by(author=self) \
|
||||
.filter(Thread.created_at > hour_ago).count() < 2 * factor
|
||||
.filter(Thread.created_at > hour_ago).count() < 2 * factor
|
||||
|
||||
def canReviewRL(self):
|
||||
from app.models import PackageReview
|
||||
@ -290,7 +309,7 @@ class User(db.Model, UserMixin):
|
||||
|
||||
hour_ago = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
|
||||
return PackageReview.query.filter_by(author=self) \
|
||||
.filter(PackageReview.created_at > hour_ago).count() < 10 * factor
|
||||
.filter(PackageReview.created_at > hour_ago).count() < 10 * factor
|
||||
|
||||
|
||||
def __eq__(self, other):
|
||||
@ -305,8 +324,8 @@ class User(db.Model, UserMixin):
|
||||
|
||||
def can_see_edit_profile(self, current_user):
|
||||
return self.checkPerm(current_user, Permission.CHANGE_USERNAMES) or \
|
||||
self.checkPerm(current_user, Permission.CHANGE_EMAIL) or \
|
||||
self.checkPerm(current_user, Permission.CHANGE_RANK)
|
||||
self.checkPerm(current_user, Permission.CHANGE_EMAIL) or \
|
||||
self.checkPerm(current_user, Permission.CHANGE_RANK)
|
||||
|
||||
def can_delete(self):
|
||||
from app.models import ForumTopic
|
||||
|
Reference in New Issue
Block a user