django-restit 4.0.2__py3-none-any.whl → 4.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-restit
3
- Version: 4.0.2
3
+ Version: 4.0.5
4
4
  Summary: A Rest Framework for DJANGO
5
5
  License: MIT
6
6
  Author: Ian Starnes
@@ -331,12 +331,17 @@ pushit/admin.py,sha256=69HdDZU_Iz8Fm72M8r8FUztsZvW37zdGwVmj8VTqr0c,451
331
331
  pushit/migrations/0001_initial.py,sha256=kYF1ksOlKf9ElrlagGhpNf5GbKEq6SORWGreMH9A7as,4555
332
332
  pushit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
333
333
  pushit/models.py,sha256=jrfreqBTThe0GvSbu16ACBMIGcZQX1534ECxVVtbVBk,5076
334
- pushit/rpc.py,sha256=qH4VQACLzqTY_iWEGMzFW8-2SQE9fny3NbJXPA64zF0,12431
334
+ pushit/rpc/__init__.py,sha256=13ibfbWNdjoNxzCzF8QxasSzFgs8IZJPc05XhErOBCw,88
335
+ pushit/rpc/githooks.py,sha256=p81qKjIcrFeQll1fKnm2pGRURWxKhT9TlH8PEHoc9po,1874
336
+ pushit/rpc/legacy.py,sha256=9xsZH1S70htIb0bwKENfhTe-uHvyqSTiPiwYTlLWS3E,5028
337
+ pushit/rpc/products.py,sha256=JFNN0VYsZQ9VJ5RZ3vD0m2hhsXEIB5Koz66inlMzx6Y,378
335
338
  pushit/static/js/models_pushit.js,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
339
+ pushit/tq.py,sha256=i3uxKfXf3bjkb1XhGWILKxxL0YwsX0TIbYjkXGbbcWU,131
340
+ pushit/utils.py,sha256=5NcWELJJjmiY2N7SiSh-qonJbLgVtFAu-EMkcFJ5St4,1966
336
341
  rest/.gitignore,sha256=TbEvWRMnAiajCTOdhiNrd9eeCAaIjRp9PRjE_VkMM5g,118
337
342
  rest/README.md,sha256=V3ETc-cJu8PZIbKr9xSe_pA4JEUpC8Dhw4bQeVCDJPw,5460
338
343
  rest/RemoteEvents.py,sha256=nL46U7AuxIrlw2JunphR1tsXyqi-ep_gD9CYGpYbNgE,72
339
- rest/__init__.py,sha256=TArumX0lGVebnvwT7qgRAdvQJcELeZTtZFrH4rn9etk,120
344
+ rest/__init__.py,sha256=Khb1uCxKcOF2h84rJaf2ZhOpxZujpN9mAvCExA7fTlc,120
340
345
  rest/arc4.py,sha256=y644IbF1ec--e4cUJ3KEYsewTCITK0gmlwa5mJruFC0,1967
341
346
  rest/cache.py,sha256=1Qg0rkaCJCaVP0-l5hZg2CIblTdeBSlj_0fP6vlKUpU,83
342
347
  rest/crypto/__init__.py,sha256=Tl0U11rgj1eBYqd6OXJ2_XSdNLumW_JkBZnaJqI6Ldw,72
@@ -344,7 +349,7 @@ rest/crypto/aes.py,sha256=f7UgiTGCfgjCc7dL94vnxkPhq_5NzooI-kw0B8_nA58,3605
344
349
  rest/crypto/privpub.py,sha256=_FioylVcbMmDP80yPYjURmafEiDmEAMkskbc7WF10ac,4082
345
350
  rest/crypto/util.py,sha256=9xrXpdI7Q9L4B6N_UKkf0tyQCSNLIxPRoEVAyJraS3Y,3955
346
351
  rest/datem.py,sha256=Tv8wF2PX0Ktr1wLgGEj6o0OW45RSkD9XDLnLRk8bRjc,7784
347
- rest/decorators.py,sha256=HQV873NjgPTbTU0UCcTYp900mXvBqsKudqYH_fCLuCo,15213
352
+ rest/decorators.py,sha256=OROP0VRNEk7FMk2WwLPnJ8olwyFX92bAsvQ7tg2tE3U,15597
348
353
  rest/encryption.py,sha256=x6Kiez0tVqfxK26MSsRL3k8OS05ni1gEX2aj3I0S9V0,788
349
354
  rest/extra/__init__.py,sha256=YzmNsch5H5FFLkUK9mIAKyoRK_rJCA9HGb0kubp4h30,54
350
355
  rest/extra/json_metadata.py,sha256=p_ffzmANmOFix_oC3voR6_NNTjcn7-T7aXcH-I4_Npg,1078
@@ -353,7 +358,7 @@ rest/forms.py,sha256=66Wm5cdy8tKib_mGicjq_yd-gNVMFWRECnrDksnNnwU,6316
353
358
  rest/helpers.py,sha256=ahTTAnsHPeBQTcxs7u-Yfjh5lP_hefDoBcIio12cYZg,23837
354
359
  rest/joke.py,sha256=0PpKaX2iN7jlS62kgjfmmqkFBYLPURz15aQ8R7OJkJ8,260
355
360
  rest/jwtoken.py,sha256=1ruZGPTXnodb85ywPd8ZmRiRYCskopA8EhcbX7Adixc,2298
356
- rest/log.py,sha256=EGrdGw2F0HIJUK7rKmQPLAEsQJq9WYum6RbYQambu4I,21139
361
+ rest/log.py,sha256=hd1_4HBOS395sfXJIL6BTw9yekm1SLgBwYx_PdfIhKA,20930
357
362
  rest/mail.py,sha256=Y7EhkFAIcX4ieSJ7KLPeECmzYQEGAjWtkLlFvD87bhA,7754
358
363
  rest/mailman.py,sha256=v5O1G5s3HiAKmz-J1z0uT6_q3xsONPpxVl9saEyQQ2I,9174
359
364
  rest/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -369,7 +374,7 @@ rest/middleware/session_store.py,sha256=X_i06TnZLW1srV0vkjjLhZ7fl1G56PswXxRpVzdF
369
374
  rest/models.py,sha256=oVaAMiHCFJRERat2e3ejDs5TTKCiZNSe6muG6hgN6uI,76845
370
375
  rest/regexes.yaml,sha256=VoGb4E-P_K9f82Yzcpltgzekpt9usRtwu9PYlo46nUw,149463
371
376
  rest/requestex.py,sha256=eD1eCPhLl7fj0oUKpESCTIr8O7mjOyBUsRXVMQ1h3W8,14894
372
- rest/rpc.py,sha256=WguTRRnz2KUzilLN7-hgvn9OM9KSmfu10ZKkpFeFPtk,3480
377
+ rest/rpc.py,sha256=KMih2Z4Z0Pqgwmcy_14nKqMCKJ9lGDJ6-vwMA2NSlyQ,3713
373
378
  rest/search.py,sha256=i7rnZZhlnuAT0isyVcMHEqGjbiz7EIArgjzzg7xwK-s,7645
374
379
  rest/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
375
380
  rest/serializers/collection.py,sha256=qpEQWl_mf_X72zFP8yNwJsDUTmc0h59KTfeFDs_Li1I,1644
@@ -393,7 +398,7 @@ rest/templates/rest_html.html,sha256=wGZV3j_tB9rzzJlsMxidUQ5ex_uRPyU_s8GCmHLXiqk
393
398
  rest/ua.py,sha256=iKoLdDFzwrmo_QfKxQoM88wPgvJabIIZPhxvIDfo5J0,185122
394
399
  rest/uberdict.py,sha256=ivDpzfchQqX8dM2_TtuyMW7NNO-j7zDmxkdKixQxvU4,17064
395
400
  rest/url_docs.py,sha256=O8O_CQso3fB-7o-huidIT1BRGv5R6lDW-yKHnsGyAPk,11881
396
- rest/urls.py,sha256=kD8tmeHr7ODe8NuC1d2R6ZGNCxcpQ8BbXdLeijwfmBc,1713
401
+ rest/urls.py,sha256=U3eD9kI19wp-NkkXCiAjdQe560fslskQngStRcGDS0I,1787
397
402
  rest/views.py,sha256=IxG3RF5txtQg7ov4H_Iymozq3NjeJ-GQNMsmdmsmExM,1056
398
403
  sessionlog/.gitignore,sha256=TbEvWRMnAiajCTOdhiNrd9eeCAaIjRp9PRjE_VkMM5g,118
399
404
  sessionlog/README.md,sha256=vQEVJ_8u3Vv19VwPfscjCiHFu61ZSrEM-KIuBpUXhws,62
@@ -441,7 +446,7 @@ ws4redis/servers/uwsgi.py,sha256=VyhoCI1DnVFqBiJYHoxqn5Idlf6uJPHvfBKgkjs34mo,172
441
446
  ws4redis/settings.py,sha256=lF-6nzv7SWjmFgmontpZKdSBhp8q4FhvFOcEYZGR8pc,1411
442
447
  ws4redis/utf8validator.py,sha256=S0OlfjeGRP75aO6CzZsF4oTjRQAgR17OWE9rgZdMBZA,5122
443
448
  ws4redis/websocket.py,sha256=R0TUyPsoVRD7Y_oU7w2I6NL4fPwiz5Vl94-fUkZgLHA,14848
444
- django_restit-4.0.2.dist-info/LICENSE.md,sha256=VHN4hhEeVOoFjtG-5fVv4jesA4SWi0Z-KgOzzN6a1ps,1068
445
- django_restit-4.0.2.dist-info/METADATA,sha256=O3oqjfC3La_pKlrhrlrvx6yYE5c5OEGTPbCpV-TqLC4,7525
446
- django_restit-4.0.2.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
447
- django_restit-4.0.2.dist-info/RECORD,,
449
+ django_restit-4.0.5.dist-info/LICENSE.md,sha256=VHN4hhEeVOoFjtG-5fVv4jesA4SWi0Z-KgOzzN6a1ps,1068
450
+ django_restit-4.0.5.dist-info/METADATA,sha256=kGdo8wXQiGHWRi1D8ix5E6DV-LIjWSpMYpL91X7L8kg,7525
451
+ django_restit-4.0.5.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
452
+ django_restit-4.0.5.dist-info/RECORD,,
pushit/rpc/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ from .githooks import * # noqa: F401, F403
2
+ from .products import * # noqa: F401, F403
pushit/rpc/githooks.py ADDED
@@ -0,0 +1,61 @@
1
+ from rest import decorators as rd
2
+ from rest import views as rv
3
+ from rest import settings
4
+ from rest import helpers as rh
5
+ from taskqueue.models import Task
6
+ from pushit import utils
7
+ import time
8
+
9
+
10
+ @rd.urlPOST('hooks/git_update')
11
+ def rest_on_git_hook(request):
12
+ sec_key = request.DATA.get("token")
13
+ git_key = settings.get("GIT_KEY", "hookswhat")
14
+ hook_request = None
15
+
16
+ req_key = request.DATA.getHeader("HTTP_X_GITLAB_TOKEN")
17
+ if req_key is not None:
18
+ hook_request = utils.parseGitLab(request)
19
+ else:
20
+ req_key = request.DATA.getHeader("HTTP_X_HUB_SIGNATURE_256")
21
+ if req_key is not None:
22
+ hook_request = utils.parseGithub(request)
23
+
24
+ if sec_key != git_key and req_key is None:
25
+ rh.error("GIT HOOK NO TOKEN", request.META)
26
+ return rv.restPermissionDenied(request)
27
+
28
+ git_projects = settings.get("GIT_PROJECTS", None)
29
+
30
+ if hook_request.name not in git_projects:
31
+ return rv.restStatus(request, False, error="no config for project")
32
+
33
+ proj_info = utils.getProjectForBranch(git_projects.get(hook_request.name), hook_request.branch)
34
+ if proj_info is None:
35
+ return rv.restStatus(request, False, error="no branch for project")
36
+
37
+ if hook_request.kind == "push":
38
+ on_git_push_request(proj_info, hook_request)
39
+
40
+ return rv.restStatus(request, True)
41
+
42
+
43
+ def on_git_push_request(info, hook_request):
44
+ branch = info.get("branch")
45
+ cmd = info.get("updater")
46
+ use_tq = info.get("use_tq", False)
47
+
48
+ if use_tq:
49
+ data = dict(branch=branch, update_cmd=cmd)
50
+ Task.Publish("pushit", "run_update", data, channel="tq_updater")
51
+ else:
52
+ asyncUpdater(cmd, branch)
53
+
54
+
55
+ @rd.rest_async
56
+ def asyncUpdater(cmd, branch):
57
+ import random
58
+ # randomize the hit so we avoid collisions (gitlabs issues)
59
+ time.sleep(random.randint(2, 15))
60
+ utils.updateCode(cmd, branch)
61
+
pushit/rpc/legacy.py ADDED
@@ -0,0 +1,126 @@
1
+ from pushit.models import Product, Release
2
+ from rest import decorators as rd
3
+
4
+
5
+ @rd.urlPOST (r'^product$')
6
+ @rd.urlPOST (r'^product/(?P<product_id>\d+)$')
7
+ @rd.urlPOST (r'^product/uuid/(?P<uuid>\w+)$')
8
+ @rd.login_optional
9
+ def updateProduct(request, product_id=None, uuid=None):
10
+ if not request.member:
11
+ return restPermissionDenied(request)
12
+ product = None
13
+ if not product_id and not uuid:
14
+ product = Product.createFromRequest(request, owner=request.member, group=request.group)
15
+ elif product_id:
16
+ product = Product.objects.filter(pk=product_id).last()
17
+ elif uuid:
18
+ product = Product.objects.filter(oid=uuid).last()
19
+
20
+ if not product:
21
+ return restStatus(request, False, error="unknown product")
22
+ if product.owner != request.member or (product.group and not request.member.isMemberOf(product.group)):
23
+ if not request.user.is_staff:
24
+ return restPermissionDenied(request)
25
+ product.saveFromRequest(request, owner=request.member)
26
+ return restGet(request, product, **Product.getGraph("default"))
27
+
28
+
29
+ @rd.urlGET (r'^product/(?P<product_id>\d+)$')
30
+ @rd.urlGET (r'^product/uuid/(?P<uuid>\w+)$')
31
+ @rd.login_optional
32
+ def getProduct(request, product_id=None, uuid=None):
33
+ product = None
34
+ if product_id:
35
+ product = Product.objects.filter(pk=product_id).last()
36
+ elif uuid:
37
+ product = Product.objects.filter(oid=uuid).last()
38
+ else:
39
+ return restNotFound(request)
40
+
41
+ if not product:
42
+ return restStatus(request, False, error="unknown product")
43
+ if not product.is_public and not request.member:
44
+ return restPermissionDenied(request, "not logged in")
45
+ return product.restGet(request)
46
+
47
+
48
+ @rd.urlGET (r'^product$')
49
+ @rd.login_optional
50
+ def listProducts(request):
51
+ if not request.member:
52
+ return restPermissionDenied(request)
53
+ if not request.member.is_staff:
54
+ return restPermissionDenied(request)
55
+
56
+ kind = request.DATA.get("kind")
57
+ qset = Product.objects.filter(archived=False)
58
+ if kind:
59
+ qset = qset.filter(kind=kind)
60
+
61
+ return restList(request, qset, **Product.getGraph("default"))
62
+
63
+
64
+ @rd.urlPOST (r'^release$')
65
+ @rd.urlPOST (r'^release/(?P<release_id>\d+)$')
66
+ @rd.login_optional
67
+ def updateRelease(request, release_id=None):
68
+ if not request.member:
69
+ return restPermissionDenied(request)
70
+
71
+ if not release_id:
72
+ auto_version = request.DATA.get("auto_version", False)
73
+ prod_uuid = request.DATA.get(["product", "product_uuid"])
74
+ product = None
75
+ if prod_uuid:
76
+ product = Product.objects.filter(oid=prod_uuid).last()
77
+ else:
78
+ prod_id = request.DATA.get("product_id")
79
+ if prod_id:
80
+ product = Product.objects.filter(pk=prod_id).last()
81
+ if not product:
82
+ return restStatus(request, False, error="product required")
83
+ version_num = request.DATA.get("version_num", field_type=int)
84
+ last_release = Release.objects.filter(product=product).order_by("-version_num").first()
85
+
86
+ if not version_num:
87
+ if last_release and auto_version:
88
+ version_num = last_release.version_num + 1
89
+ elif auto_version:
90
+ version_num = 1
91
+ else:
92
+ return restStatus(request, False, error="no version info supplied, try auto_version=1")
93
+ elif last_release and version_num <= last_release.version_num:
94
+ return restStatus(request, False, error="version is not greater then last")
95
+
96
+ release = Release.createFromRequest(request, product=product, owner=request.member, group=request.group, version_num=version_num)
97
+ else:
98
+ release = Release.objects.filter(pk=release_id).last()
99
+ if not release:
100
+ return restStatus(request, False, error="unknown release")
101
+ if release.owner != request.member or (release.product.group and not request.member.isMemberOf(release.product.group)):
102
+ if not request.user.is_staff:
103
+ return restPermissionDenied(request)
104
+ release.saveFromRequest(request, owner=request.member)
105
+ if request.DATA.get("make_current"):
106
+ release.makeCurrent()
107
+ elif request.DATA.get("make_beta"):
108
+ release.makeCurrent()
109
+ return restGet(request, release, **Release.getGraph("default"))
110
+
111
+
112
+ @rd.urlGET (r'^release/(?P<release_id>\d+)$')
113
+ @rd.login_optional
114
+ def getRelease(request, release_id):
115
+ release = Release.objects.filter(pk=release_id).last()
116
+ if not release:
117
+ return restStatus(request, False, error="unknown release")
118
+ if not release.product.is_public and not request.member:
119
+ return restPermissionDenied(request, "not logged in")
120
+ return restGet(request, release, **Release.getGraph("default"))
121
+
122
+
123
+ def reportRestIssue(subject, message, perm="rest_errors", email_only=False):
124
+ # notifyWithPermission(perm, subject, message=None, template=None, context=None, email_only=False)
125
+ # notify email only
126
+ Member.notifyWithPermission(perm, subject, message, email_only=email_only)
pushit/rpc/products.py ADDED
@@ -0,0 +1,15 @@
1
+ from rest import decorators as rd
2
+ from rest import views as rv
3
+ from pushit.models import Product, Release
4
+
5
+
6
+ @rd.url('product')
7
+ @rd.url('product/<int:pk>')
8
+ def rest_on_product(request, pk=None):
9
+ return Product.on_rest_request(request, pk)
10
+
11
+
12
+ @rd.url('release')
13
+ @rd.url('release/<int:pk>')
14
+ def rest_on_release(request, pk=None):
15
+ return Release.on_rest_request(request, pk)
pushit/tq.py ADDED
@@ -0,0 +1,6 @@
1
+ from pushit import utils
2
+
3
+
4
+ def run_update(task):
5
+ utils.run_update(task.data.update_cmd, task.data.branch)
6
+ task.completed()
pushit/utils.py ADDED
@@ -0,0 +1,58 @@
1
+ from rest import settings
2
+ from rest import log
3
+ from objict import objict
4
+ import os
5
+ import subprocess
6
+
7
+ logger = log.getLogger("pushit", filename="pushit.log")
8
+
9
+
10
+ def updateCode(update_cmd, branch, update_user="ec2-user"):
11
+ if settings.PUSHIT_TEST_SUDO:
12
+ cmd = ["sudo", "-lU", update_user, update_cmd, branch]
13
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
14
+ out, err = process.communicate()
15
+ if err.strip():
16
+ logger.warning("WARNING: cannot run {}, we don't have sudo rights".format(update_cmd))
17
+ logger.warning("WARNING: add {} to your sudo user".format(update_cmd))
18
+ return
19
+ # - lock it so we kill any updates in progress and start a new one
20
+ cmd = ["sudo", "-u", update_user, update_cmd, branch]
21
+ logger.info("updating...", cmd)
22
+ subprocess.Popen(cmd, close_fds=True)
23
+
24
+
25
+ def parseGitLab(request):
26
+ info = objict(vendor="gitlab")
27
+ info.name = request.DATA.get("project.name")
28
+ info.kind = request.DATA.get("object_kind")
29
+ if "ref" in request.DATA:
30
+ info.branch = request.DATA.get("ref").split('/')[-1]
31
+ if info.kind == "merge_request":
32
+ info.state = request.DATA.get("object_attributes.state", None)
33
+ if info.state == "merged":
34
+ info.kind = "merged"
35
+ return info
36
+
37
+
38
+ def parseGithub(request):
39
+ info = objict(vendor="github")
40
+ info.name = request.DATA.get("repository.name")
41
+ info.kind = request.DATA.getHeader("HTTP_X_GITHUB_EVENT")
42
+ if "ref" in request.DATA:
43
+ info.branch = request.DATA.get("ref").split('/')[-1]
44
+ logger.info("github request", info)
45
+ return info
46
+
47
+
48
+ def getProjectForBranch(proj_info, branch):
49
+ if proj_info is None:
50
+ return None
51
+ if isinstance(proj_info, list):
52
+ for pi in proj_info:
53
+ if pi["branch"] == branch:
54
+ return pi
55
+ return None
56
+ if proj_info["branch"] == branch:
57
+ return proj_info
58
+ return None
rest/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  from .uberdict import UberDict # noqa: F401
2
2
  from .settings_helper import settings # noqa: F401
3
3
 
4
- __version__ = "5.4.0"
4
+ __version__ = "4.0.5"
rest/decorators.py CHANGED
@@ -18,12 +18,14 @@ from datetime import datetime
18
18
  from auditlog.models import PersistentLog
19
19
 
20
20
  import importlib
21
+ import pkgutil
21
22
  import threading
22
23
  import traceback
23
24
 
24
25
  REST_METRICS = settings.get("REST_METRICS", False)
25
26
  REST_METRICS_BY_ENDPOINT = settings.get("REST_METRICS_BY_ENDPOINT", False)
26
27
  REST_METRICS_IGNORE = settings.get("REST_METRICS_IGNORE", [])
28
+ REST_MODULE_NAME = settings.get("REST_MODULE_NAME", "rpc")
27
29
 
28
30
 
29
31
  # background task (no return)
@@ -130,6 +132,12 @@ def dispatcher(request, *args, **kwargs):
130
132
  return restStatus(request, False, error="endpoint not found", error_code=404)
131
133
 
132
134
 
135
+ def _load_module(mod):
136
+ if pkgutil.find_loader(mod) is not None:
137
+ return importlib.import_module(mod)
138
+ return None
139
+
140
+
133
141
  def _url_method(pattern, method=None, *args, **kwargs):
134
142
  """
135
143
  Register a view handler for a specific HTTP method
@@ -150,13 +158,17 @@ def _url_method(pattern, method=None, *args, **kwargs):
150
158
  # print module.__name__
151
159
  root_name = module.__name__.split('.')[0]
152
160
  # print "importing {0}.rpc".format(root_name)
153
- rpc_root_module = importlib.import_module(root_name + ".rpc")
161
+ rmodule = _load_module(f"{root_name}.{REST_MODULE_NAME}")
162
+ if rmodule is not None:
163
+ rpc_root_module = rmodule
154
164
  # print "{0}/{1}".format(rpc_root_module.__name__, pattern)
155
- elif not module.__name__.endswith(".rpc") and module.__name__.count('.'):
165
+ elif not module.__name__.endswith(f".{REST_MODULE_NAME}") and module.__name__.count('.'):
156
166
  # print module.__name__
157
167
  root_name = module.__name__.split('.')[0]
158
168
  # print "importing {0}.rpc".format(root_name)
159
- rpc_root_module = importlib.import_module(root_name + ".rpc")
169
+ rmodule = _load_module(f"{root_name}.{REST_MODULE_NAME}")
170
+ if rmodule is not None:
171
+ rpc_root_module = rmodule
160
172
  lmethod = method
161
173
  if lmethod is None:
162
174
  lmethod = "ALL"
rest/log.py CHANGED
@@ -12,7 +12,11 @@ import sys
12
12
  import threading
13
13
  import time
14
14
  import traceback
15
+ from .settings_helper import settings
15
16
 
17
+ LOG_FOLDER = settings.LOG_ROOT
18
+ if LOG_FOLDER is None:
19
+ LOG_FOLDER = os.path.join(settings.BASE_DIR, "var", "logs")
16
20
 
17
21
  COLOR_LOGS = True
18
22
  MAX_LOG_SIZE = 10485760
@@ -21,19 +25,6 @@ MAX_LOG_SIZE = 10485760
21
25
  ROTATE_LEFT_OVER_BYTES = 50000
22
26
  LOG_COUNT = 3
23
27
 
24
- REST_FOLDER = os.path.realpath(__file__)
25
- # now work backwards until we find folder with "django"
26
- ROOT = None
27
- CUR_FOLDER = REST_FOLDER
28
- while ROOT is None:
29
- if os.path.exists(os.path.join(CUR_FOLDER, "django")):
30
- ROOT = CUR_FOLDER
31
- else:
32
- CUR_FOLDER = os.path.dirname(CUR_FOLDER)
33
-
34
- VAR_FOLDER = os.path.join(ROOT, "var", "logs")
35
- PATH = VAR_FOLDER
36
-
37
28
 
38
29
  class RestLogManager(object):
39
30
  def __init__(self):
@@ -121,8 +112,8 @@ def getLogger(
121
112
  LOG_MANAGER.loggers[name] = rest_logger
122
113
  if set_master:
123
114
  LOG_MANAGER.master = rest_logger
124
- if not os.path.exists(VAR_FOLDER):
125
- mkdir(VAR_FOLDER)
115
+ if not os.path.exists(LOG_FOLDER):
116
+ mkdir(LOG_FOLDER)
126
117
  except Exception as err:
127
118
  print((str(err)))
128
119
  print((str(traceback.format_exc())))
@@ -160,7 +151,7 @@ class RestLoggerStream(object):
160
151
  if not os.path.exists(self.filename):
161
152
  path, fname = os.path.split(filename)
162
153
  if not len(path):
163
- self.filename = os.path.join(VAR_FOLDER, filename)
154
+ self.filename = os.path.join(LOG_FOLDER, filename)
164
155
  self.max_bytes = max_bytes
165
156
  self.stream = None
166
157
  self.is_stdout = False
rest/rpc.py CHANGED
@@ -31,6 +31,13 @@ def on_get_version(request):
31
31
  return views.restStatus(request, True, {"data": version.VERSION})
32
32
 
33
33
 
34
+ @url(r'^versions$')
35
+ def on_get_version(request):
36
+ from rest import __version__ as restit_version
37
+ versions = dict(project=version.VERSION, restit=restit_version)
38
+ return views.restStatus(request, True, {"data": versions})
39
+
40
+
34
41
  @url(r'^joke$')
35
42
  def on_get_joke(request):
36
43
  return views.restGet(request, {"joke": joke.getRandomJoke()})
rest/urls.py CHANGED
@@ -24,7 +24,9 @@ urlpatterns = [
24
24
  def load_app(app, root_module=None):
25
25
  module = None
26
26
  try:
27
- module = loadModule(app + '.rpc')
27
+ module = loadModule(f"{app}.rpc")
28
+ if module is None:
29
+ module = loadModule(f"{app}.rurl")
28
30
  except ImportError as err:
29
31
  print("**** failed to load {0}.rpc! ****".format(app))
30
32
  print("**** missing dependencies ****")
pushit/rpc.py DELETED
@@ -1,334 +0,0 @@
1
- from django.db import models
2
-
3
-
4
- from account.models import Member
5
-
6
- from rest.views import *
7
- from rest.decorators import *
8
- from rest import search
9
- from rest import helpers
10
- from rest import crypto
11
- from rest import log
12
- from rest import settings
13
-
14
-
15
- logger = log.getLogger("pushit", filename="pushit.log")
16
-
17
- from objict import objict
18
-
19
- from pushit.models import Product, Release
20
-
21
- import json
22
-
23
- import base64
24
-
25
- from datetime import datetime, timedelta
26
- import time
27
-
28
- @urlPOST (r'^product$')
29
- @urlPOST (r'^product/(?P<product_id>\d+)$')
30
- @urlPOST (r'^product/uuid/(?P<uuid>\w+)$')
31
- @login_optional
32
- def updateProduct(request, product_id=None, uuid=None):
33
- if not request.member:
34
- return restPermissionDenied(request)
35
- product = None
36
- if not product_id and not uuid:
37
- product = Product.createFromRequest(request, owner=request.member, group=request.group)
38
- elif product_id:
39
- product = Product.objects.filter(pk=product_id).last()
40
- elif uuid:
41
- product = Product.objects.filter(oid=uuid).last()
42
-
43
- if not product:
44
- return restStatus(request, False, error="unknown product")
45
- if product.owner != request.member or (product.group and not request.member.isMemberOf(product.group)):
46
- if not request.user.is_staff:
47
- return restPermissionDenied(request)
48
- product.saveFromRequest(request, owner=request.member)
49
- return restGet(request, product, **Product.getGraph("default"))
50
-
51
- @urlGET (r'^product/(?P<product_id>\d+)$')
52
- @urlGET (r'^product/uuid/(?P<uuid>\w+)$')
53
- @login_optional
54
- def getProduct(request, product_id=None, uuid=None):
55
- product = None
56
- if product_id:
57
- product = Product.objects.filter(pk=product_id).last()
58
- elif uuid:
59
- product = Product.objects.filter(oid=uuid).last()
60
- else:
61
- return restNotFound(request)
62
-
63
- if not product:
64
- return restStatus(request, False, error="unknown product")
65
- if not product.is_public and not request.member:
66
- return restPermissionDenied(request, "not logged in")
67
- return product.restGet(request)
68
-
69
- @urlGET (r'^product$')
70
- @login_optional
71
- def listProducts(request):
72
- if not request.member:
73
- return restPermissionDenied(request)
74
- if not request.member.is_staff:
75
- return restPermissionDenied(request)
76
-
77
- kind = request.DATA.get("kind")
78
- qset = Product.objects.filter(archived=False)
79
- if kind:
80
- qset = qset.filter(kind=kind)
81
-
82
- return restList(request, qset, **Product.getGraph("default"))
83
-
84
- @urlPOST (r'^release$')
85
- @urlPOST (r'^release/(?P<release_id>\d+)$')
86
- @login_optional
87
- def updateRelease(request, release_id=None):
88
- if not request.member:
89
- return restPermissionDenied(request)
90
-
91
- if not release_id:
92
- auto_version = request.DATA.get("auto_version", False)
93
- prod_uuid = request.DATA.get(["product", "product_uuid"])
94
- product = None
95
- if prod_uuid:
96
- product = Product.objects.filter(oid=prod_uuid).last()
97
- else:
98
- prod_id = request.DATA.get("product_id")
99
- if prod_id:
100
- product = Product.objects.filter(pk=prod_id).last()
101
- if not product:
102
- return restStatus(request, False, error="product required")
103
- version_num = request.DATA.get("version_num", field_type=int)
104
- last_release = Release.objects.filter(product=product).order_by("-version_num").first()
105
-
106
- if not version_num:
107
- if last_release and auto_version:
108
- version_num = last_release.version_num + 1
109
- elif auto_version:
110
- version_num = 1
111
- else:
112
- return restStatus(request, False, error="no version info supplied, try auto_version=1")
113
- elif last_release and version_num <= last_release.version_num:
114
- return restStatus(request, False, error="version is not greater then last")
115
-
116
- release = Release.createFromRequest(request, product=product, owner=request.member, group=request.group, version_num=version_num)
117
- else:
118
- release = Release.objects.filter(pk=release_id).last()
119
- if not release:
120
- return restStatus(request, False, error="unknown release")
121
- if release.owner != request.member or (release.product.group and not request.member.isMemberOf(release.product.group)):
122
- if not request.user.is_staff:
123
- return restPermissionDenied(request)
124
- release.saveFromRequest(request, owner=request.member)
125
- if request.DATA.get("make_current"):
126
- release.makeCurrent()
127
- elif request.DATA.get("make_beta"):
128
- release.makeCurrent()
129
- return restGet(request, release, **Release.getGraph("default"))
130
-
131
- @urlGET (r'^release/(?P<release_id>\d+)$')
132
- @login_optional
133
- def getRelease(request, release_id):
134
- release = Release.objects.filter(pk=release_id).last()
135
- if not release:
136
- return restStatus(request, False, error="unknown release")
137
- if not release.product.is_public and not request.member:
138
- return restPermissionDenied(request, "not logged in")
139
- return restGet(request, release, **Release.getGraph("default"))
140
-
141
- def reportRestIssue(subject, message, perm="rest_errors", email_only=False):
142
- # notifyWithPermission(perm, subject, message=None, template=None, context=None, email_only=False)
143
- # notify email only
144
- Member.notifyWithPermission(perm, subject, message, email_only=email_only)
145
-
146
- from random import randint
147
- @rest_async
148
- def update_code(git_updater, updater_md5=None, branch=None):
149
- # randomize the hit so we avoid collisions (gitlabs issues)
150
- time.sleep(randint(1, 10))
151
- import os
152
- import subprocess
153
- # check md5sum
154
- if updater_md5:
155
- cur_md5 = crypto.getFileMD5(git_updater)
156
- if cur_md5.lower() != updater_md5.lower():
157
- reportRestIssue("md5 check failed", "{}\ncould not be executed, md5 check failed".format(git_updater))
158
- return
159
-
160
- # TODO
161
- # - check for errors and permissions
162
- if settings.PUSHIT_TEST_SUDO:
163
- cmd = ["sudo", "-lU", "ec2-user", git_updater, branch]
164
- process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
165
- out, err = process.communicate()
166
- if err.strip():
167
- logger.warning("WARNING: cannot run {}, we don't have sudo rights".format(git_updater))
168
- logger.warning("WARNING: add {} to your sudo user".format(git_updater))
169
- return
170
- # - lock it so we kill any updates in progress and start a new one
171
- cmd = ["sudo", "-u", "ec2-user", git_updater, branch]
172
- logger.info("updating...", cmd)
173
- subprocess.Popen(cmd, close_fds=True)
174
-
175
- @rest_async
176
- def new_release(product, tag, url, msg):
177
- version_str = tag
178
- if tag.startswith("v"):
179
- version_str = tag[1:]
180
-
181
- rev = tag.split('.')[-1]
182
- if not rev.isdigit():
183
- return False
184
- token = product.getProperty("git_token", "XXXXX")
185
- release = Release(product=product, version_num=int(rev), version_str=version_str, notes=msg)
186
- release.owner = product.owner
187
- release_url = "{}/repository/{}/archive.zip?private_token={}".format(url, tag, token)
188
- release.save()
189
- logger.info(release_url)
190
- release.set_media(release_url, True)
191
- release.makeCurrent()
192
-
193
- def on_git_merge_request(info, request):
194
- state = request.DATA.get("object_attributes.state")
195
- target_branch = request.DATA.get("object_attributes.target_branch")
196
-
197
- git_branch = info.get("branch")
198
- git_updater = info.get("updater")
199
- git_updater_md5 = info.get("updater_md5", None)
200
-
201
- if target_branch == git_branch:
202
- reportRestIssue(
203
- "{} update({}) on: {}".format(info.get("project", "n/a"), settings.get("SERVER_NAME", "unknown"), git_branch),
204
- "<pre>{}</pre>".format(helpers.dictToString(request.DATA.asDict(), True)),
205
- "git_updates", email_only=True)
206
- update_code(git_updater, git_updater_md5, git_branch)
207
-
208
- def on_git_push_request(info, hook_request):
209
- git_branch = info.get("branch")
210
- git_updater = info.get("updater")
211
- git_updater_md5 = info.get("updater_md5", None)
212
- update_code(git_updater, git_updater_md5, git_branch)
213
-
214
- def on_git_new_release(info, request):
215
- project = request.DATA.get("project.name")
216
- logger.info("NEW RELEASE FOR {}".format(project))
217
- product = Product.objects.filter(name=project).last()
218
- if not product:
219
- logger.info("PRODUCT NOT FOUND")
220
- return
221
- tag = request.DATA.get("ref").split('/')[-1]
222
- msg = request.DATA.get("message")
223
- url = request.DATA.get("project.web_url")
224
- if product and msg:
225
- new_release(product, tag, url, msg)
226
-
227
-
228
- def parseGitLab(request):
229
- info = objict(vendor="gitlab")
230
- info.name = request.DATA.get("project.name")
231
- info.kind = request.DATA.get("object_kind")
232
- if "ref" in request.DATA:
233
- info.branch = request.DATA.get("ref").split('/')[-1]
234
- if info.kind == "merge_request":
235
- info.state = request.DATA.get("object_attributes.state", None)
236
- if info.state == "merged":
237
- info.kind = "merged"
238
- return info
239
-
240
-
241
- def parseGithub(request):
242
- info = objict(vendor="github")
243
- info.name = request.DATA.get("repository.name")
244
- info.kind = request.DATA.getHeader("HTTP_X_GITHUB_EVENT")
245
- if "ref" in request.DATA:
246
- info.branch = request.DATA.get("ref").split('/')[-1]
247
- logger.info("github request", info)
248
- return info
249
-
250
-
251
- def getProjectForBranch(proj_info, branch):
252
- if proj_info is None:
253
- return None
254
- if type(proj_info) is list:
255
- for pi in proj_info:
256
- if pi["branch"] == branch:
257
- return pi
258
- return None
259
- if project_info["branch"] == branch:
260
- return proj_info
261
- return None
262
-
263
-
264
- @urlPOST (r'^hooks/git_update$')
265
- def on_git_hook(request):
266
- sec_key = request.DATA.get("token")
267
- git_key = settings.get("GIT_KEY", "hookswhat")
268
- is_gitlab = True
269
- hook_request = None
270
- req_key = request.DATA.getHeader("HTTP_X_GITLAB_TOKEN")
271
- if req_key is not None:
272
- logger.info("GITLAB Detected")
273
- hook_request = parseGitLab(request)
274
- else:
275
- req_key = request.DATA.getHeader("HTTP_X_HUB_SIGNATURE_256")
276
- if req_key is not None:
277
- is_gitlab = False
278
- logger.info("GITHUB Detected")
279
- hook_request = parseGithub(request)
280
-
281
- if sec_key != git_key:
282
- if req_key is None:
283
- logger.warning("NO TOKEN")
284
- logger.warning(request.META)
285
- return restPermissionDenied(request)
286
-
287
- git_projects = settings.get("GIT_PROJECTS", None)
288
-
289
- if hook_request.name not in git_projects:
290
- return restStatus(request, False, error="no config for project")
291
-
292
- proj_info = getProjectForBranch(git_projects.get(hook_request.name), hook_request.branch)
293
- if proj_info is None:
294
- logger.info("no branch for project", hook_request)
295
- return restStatus(request, False, error="no branch for project")
296
-
297
- if hook_request.kind == "push":
298
- on_git_push_request(proj_info, hook_request)
299
-
300
- # kind = request.DATA.get("object_kind")
301
- # project = request.DATA.get("project.name")
302
-
303
- # git_projects = settings.get("GIT_PROJECTS", None)
304
- # if git_projects and project in git_projects:
305
- # proj_info = git_projects.get(project)
306
- # # now lets handle different kinds
307
- # if kind == "merge_request":
308
- # # now check the state
309
- # state = request.DATA.get("object_attributes.state", None)
310
- # if state != "merged":
311
- # return restStatus(request, True)
312
- # if type(proj_info) is list:
313
- # for info in proj_info:
314
- # info["project"] = project
315
- # on_git_merge_request(info, request)
316
- # else:
317
- # on_git_merge_request(proj_info, request)
318
- # elif kind == "push":
319
- # if type(proj_info) is list:
320
- # for info in proj_info:
321
- # info["project"] = project
322
- # on_git_push_request(info, request)
323
- # else:
324
- # proj_info["project"] = project
325
- # on_git_push_request(proj_info, request)
326
- # elif kind == "tag_push":
327
- # on_git_new_release(proj_info, request)
328
- # elif kind == "tag_push":
329
- # proj_info = git_projects.get(project)
330
- # on_git_new_release(proj_info, request)
331
- # else:
332
- # helpers.log_print("No Config for Project {}".format(project))
333
- return restStatus(request, True)
334
-