]> git.lizzy.rs Git - cheatdb.git/blob - app/blueprints/api/endpoints.py
5aa4dd70f7b06086745a75dc3a11943e1ffa3a3e
[cheatdb.git] / app / blueprints / api / endpoints.py
1 # ContentDB
2 # Copyright (C) 2018  rubenwardy
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17
18 from flask import *
19 from flask_user import *
20 from . import bp
21 from .auth import is_api_authd
22 from .support import error, handleCreateRelease
23 from app import csrf
24 from app.models import *
25 from app.utils import is_package_page
26 from app.markdown import render_markdown
27 from app.querybuilder import QueryBuilder
28
29 @bp.route("/api/packages/")
30 def packages():
31         qb    = QueryBuilder(request.args)
32         query = qb.buildPackageQuery()
33         ver   = qb.getMinetestVersion()
34
35         pkgs = [package.getAsDictionaryShort(current_app.config["BASE_URL"], version=ver) \
36                         for package in query.all()]
37         return jsonify(pkgs)
38
39
40 @bp.route("/api/scores/")
41 def package_scores():
42         qb    = QueryBuilder(request.args)
43         query = qb.buildPackageQuery()
44
45         pkgs = [package.getScoreDict() for package in query.all()]
46         return jsonify(pkgs)
47
48
49 @bp.route("/api/packages/<author>/<name>/")
50 @is_package_page
51 def package(package):
52         return jsonify(package.getAsDictionary(current_app.config["BASE_URL"]))
53
54
55 def resolve_package_deps(out, package, only_hard):
56         id = package.getId()
57         if id in out:
58                 return
59
60         ret = []
61         out[id] = ret
62
63         for dep in package.dependencies:
64                 if only_hard and dep.optional:
65                         continue
66
67                 name = None
68                 fulfilled_by = None
69
70                 if dep.package:
71                         name = dep.package.name
72                         fulfilled_by = [ dep.package.getId() ]
73                         resolve_package_deps(out, dep.package, only_hard)
74
75                 elif dep.meta_package:
76                         name = dep.meta_package.name
77                         fulfilled_by = [ pkg.getId() for pkg in dep.meta_package.packages]
78                         # TODO: resolve most likely candidate
79
80                 else:
81                         raise "Malformed dependency"
82
83                 ret.append({
84                         "name": name,
85                         "is_optional": dep.optional,
86                         "packages": fulfilled_by
87                 })
88
89
90 @bp.route("/api/packages/<author>/<name>/dependencies/")
91 @is_package_page
92 def package_dependencies(package):
93         only_hard = request.args.get("only_hard")
94
95         out = {}
96         resolve_package_deps(out, package, only_hard)
97
98         return jsonify(out)
99
100
101 @bp.route("/api/packages/<author>/<name>/releases/")
102 @is_package_page
103 def list_releases(package):
104         releases = package.releases.filter_by(approved=True).all()
105         return jsonify([ rel.getAsDictionary() for rel in releases ])
106
107
108 @bp.route("/api/topics/")
109 def topics():
110         qb     = QueryBuilder(request.args)
111         query  = qb.buildTopicQuery(show_added=True)
112         return jsonify([t.getAsDictionary() for t in query.all()])
113
114
115 @bp.route("/api/topic_discard/", methods=["POST"])
116 @login_required
117 def topic_set_discard():
118         tid = request.args.get("tid")
119         discard = request.args.get("discard")
120         if tid is None or discard is None:
121                 abort(400)
122
123         topic = ForumTopic.query.get(tid)
124         if not topic.checkPerm(current_user, Permission.TOPIC_DISCARD):
125                 abort(403)
126
127         topic.discarded = discard == "true"
128         db.session.commit()
129
130         return jsonify(topic.getAsDictionary())
131
132
133 @bp.route("/api/minetest_versions/")
134 def versions():
135         return jsonify([{ "name": rel.name, "protocol_version": rel.protocol }\
136                         for rel in MinetestRelease.query.all() if rel.getActual() is not None])
137
138
139 @bp.route("/api/whoami/")
140 @is_api_authd
141 def whoami(token):
142         if token is None:
143                 return jsonify({ "is_authenticated": False, "username": None })
144         else:
145                 return jsonify({ "is_authenticated": True, "username": token.owner.username })
146
147
148 @bp.route("/api/markdown/", methods=["POST"])
149 @csrf.exempt
150 def markdown():
151         return render_markdown(request.data.decode("utf-8"))
152
153
154 @bp.route("/api/packages/<author>/<name>/releases/new/", methods=["POST"])
155 @csrf.exempt
156 @is_package_page
157 @is_api_authd
158 def create_release(token, package):
159         if not token:
160                 error(401, "Authentication needed")
161
162         if not package.checkPerm(token.owner, Permission.APPROVE_RELEASE):
163                 error(403, "You do not have the permission to approve releases")
164
165         json = request.json
166         if json is None:
167                 error(400, "JSON post data is required")
168
169         for option in ["method", "title", "ref"]:
170                 if json.get(option) is None:
171                         error(400, option + " is required in the POST data")
172
173         if json["method"].lower() != "git":
174                 error(400, "Release-creation methods other than git are not supported")
175
176         return handleCreateRelease(token, package, json["title"], json["ref"])