Skip to content

Commit 128c71c

Browse files
committed
Merge branch 'master' of github.com:tutorcruncher/socket-server into heroku-ready
2 parents e08cfff + 21bf703 commit 128c71c

25 files changed

+775
-82
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
POSTGRES_PASSWORD: postgres
2121
POSTGRES_DB: socket_test
2222
ports:
23-
- 5432:5432
23+
- 5432:5432
2424
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
2525
redis:
2626
image: redis
@@ -29,7 +29,7 @@ jobs:
2929
options: --entrypoint redis-server
3030

3131
env:
32-
DATABASE_URL: 'postgres://postgres:postgres@localhost:5432/socket_test'
32+
DATABASE_URL: 'postgres://postgres:postgres@127.0.0.1:5432/socket_test'
3333

3434
steps:
3535
- uses: actions/checkout@v2

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
socket-server
22
=============
33

4-
[![Build Status](https://github.com/tutorcruncher/socket-server/workflows/CI/badge.svg)
4+
![Build Status](https://github.com/tutorcruncher/socket-server/workflows/CI/badge.svg)
55
[![codecov](https://codecov.io/gh/tutorcruncher/socket-server/branch/master/graph/badge.svg)](https://codecov.io/gh/tutorcruncher/socket-server)
66

77
Backend application for [TutorCruncher's](https://tutorcruncher.com) web integration.

runtime.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
python-3.8.3
1+
python-3.8.8

tcsocket/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.6-alpine
1+
FROM python:3.8.8-alpine
22

33
RUN apk --update --no-cache add gcc g++ musl-dev zlib-dev libuv libffi-dev make postgresql-dev jpeg-dev tiff-dev \
44
&& rm -rf /var/cache/apk/*

tcsocket/app/main.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,25 @@
1212
from .views.appointments import (
1313
appointment_list,
1414
appointment_webhook,
15+
appointment_webhook_clear,
1516
appointment_webhook_delete,
17+
appointment_webhook_mass,
1618
book_appointment,
1719
check_client,
1820
service_list,
1921
)
2022
from .views.company import company_create, company_list, company_options, company_update
21-
from .views.contractor import contractor_get, contractor_list, contractor_set
23+
from .views.contractor import contractor_get, contractor_list, contractor_set, contractor_set_mass
2224
from .views.enquiry import clear_enquiry, enquiry
2325

2426

2527
async def startup(app: web.Application):
2628
settings: Settings = app['settings']
2729
redis = await create_pool(settings.redis_settings)
2830
app.update(
29-
pg_engine=await create_engine(settings.pg_dsn), redis=redis, session=ClientSession(),
31+
pg_engine=await create_engine(settings.pg_dsn),
32+
redis=redis,
33+
session=ClientSession(),
3034
)
3135

3236

@@ -50,11 +54,18 @@ def setup_routes(app):
5054
# to work with tutorcruncher websockets
5155
app.router.add_post(r'/{company}/webhook/options', company_update, name='company-update')
5256
app.router.add_post(r'/{company}/webhook/contractor', contractor_set, name='webhook-contractor')
57+
app.router.add_post(r'/{company}/webhook/contractor/mass', contractor_set_mass, name='webhook-contractor-mass')
5358
app.router.add_post(r'/{company}/webhook/clear-enquiry', clear_enquiry, name='webhook-clear-enquiry')
5459
app.router.add_post(r'/{company}/webhook/appointments/{id:\d+}', appointment_webhook, name='webhook-appointment')
60+
app.router.add_post(
61+
r'/{company}/webhook/appointments/mass', appointment_webhook_mass, name='webhook-appointment-mass'
62+
)
5563
app.router.add_delete(
5664
r'/{company}/webhook/appointments/{id:\d+}', appointment_webhook_delete, name='webhook-appointment-delete'
5765
)
66+
app.router.add_delete(
67+
r'/{company}/webhook/appointments/clear', appointment_webhook_clear, name='webhook-appointment-clear'
68+
)
5869

5970
app.router.add_get(r'/{company}/contractors', contractor_list, name='contractor-list')
6071
app.router.add_get(r'/{company}/contractors/{id:\d+}', contractor_get, name='contractor-get')

tcsocket/app/middleware.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ async def company_middleware(request, handler):
164164
request['company'] = company
165165
else:
166166
raise HTTPNotFoundJson(
167-
status='company not found', details=f'No company found for key {public_key}',
167+
status='company not found',
168+
details=f'No company found for key {public_key}',
168169
)
169170
return await handler(request)
170171
except CancelledError:
@@ -190,7 +191,8 @@ async def json_request_middleware(request, handler):
190191

191192
if error_details:
192193
raise HTTPBadRequestJson(
193-
status='invalid request data', details=error_details,
194+
status='invalid request data',
195+
details=error_details,
194196
)
195197
return await handler(request)
196198

@@ -202,7 +204,8 @@ def _check_timestamp(ts: str, now):
202204
raise ValueError()
203205
except (TypeError, ValueError):
204206
raise HTTPForbiddenJson(
205-
status='invalid request time', details=f"request time '{ts}' not in the last 10 seconds",
207+
status='invalid request time',
208+
details=f"request time '{ts}' not in the last 10 seconds",
206209
)
207210

208211

@@ -221,7 +224,8 @@ async def authenticate(request, api_key=None):
221224
if _api_key and signature == hmac.new(_api_key, body, hashlib.sha256).hexdigest():
222225
return
223226
raise HTTPUnauthorizedJson(
224-
status='invalid signature', details=f'Signature header "{signature}" does not match computed signature',
227+
status='invalid signature',
228+
details=f'Signature header "{signature}" does not match computed signature',
225229
)
226230

227231

tcsocket/app/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ class Contractor(Base):
4444
id = Column(Integer, primary_key=True, autoincrement=False, nullable=False)
4545
company = Column(Integer, ForeignKey('companies.id'), nullable=False)
4646

47-
first_name = Column(String(63), index=True)
48-
last_name = Column(String(63))
47+
first_name = Column(String(255), index=True)
48+
last_name = Column(String(255))
4949

5050
town = Column(String(63))
5151
country = Column(String(63))

tcsocket/app/processing.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,14 @@ def _get_special_extra_attr(extra_attributes: List[ExtraAttributeModel], machine
108108

109109

110110
async def contractor_set(
111-
*, conn, company, contractor: ContractorModel, skip_deleted=False, redis=None, ctx=None,
111+
*,
112+
conn,
113+
company,
114+
contractor: ContractorModel,
115+
process_profile_pic=True,
116+
skip_deleted=False,
117+
redis=None,
118+
ctx=None,
112119
) -> Action:
113120
"""
114121
Create or update a contractor.
@@ -119,6 +126,7 @@ async def contractor_set(
119126
:param company: dict with company info, including id and public_key
120127
:param contractor: data about contractor
121128
:param skip_deleted: whether or not to skip deleted contractors (or delete them in the db.)
129+
:param process_profile_pic: whether or not to run process_image
122130
:return: Action: created, updated or deleted
123131
"""
124132
from .worker import process_image
@@ -132,7 +140,8 @@ async def contractor_set(
132140
)
133141
if not await curr.first():
134142
raise HTTPNotFoundJson(
135-
status='not found', details=f'contractor with id {contractor.id} not found',
143+
status='not found',
144+
details=f'contractor with id {contractor.id} not found',
136145
)
137146
return Action.deleted
138147

@@ -174,11 +183,12 @@ async def contractor_set(
174183
if r is None:
175184
# the contractor already exists but on another company
176185
raise HTTPForbiddenJson(
177-
status='permission denied', details=f'you do not have permission to update contractor {contractor.id}',
186+
status='permission denied',
187+
details=f'you do not have permission to update contractor {contractor.id}',
178188
)
179189
await _set_skills(conn, contractor.id, contractor.skills)
180190
await _set_labels(conn, company['id'], contractor.labels)
181-
if contractor.photo:
191+
if process_profile_pic and contractor.photo:
182192
# Sometimes creating the contractor is already done on a job, so don't need another one.
183193
job_kwargs = dict(company_key=company['public_key'], contractor_id=contractor.id, url=contractor.photo)
184194
if redis:

tcsocket/app/settings.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ class Settings(BaseSettings):
3333
def parse_redis_settings(cls, v):
3434
conf = urlparse(v)
3535
return RedisSettings(
36-
host=conf.hostname, port=conf.port, password=conf.password, database=int((conf.path or '0').strip('/')),
36+
host=conf.hostname,
37+
port=conf.port,
38+
password=conf.password,
39+
database=int((conf.path or '0').strip('/')),
3740
)
3841

3942
@property

tcsocket/app/utils.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ def pretty_lenient_json(data):
5151
class HTTPClientErrorJson(web.HTTPClientError):
5252
def __init__(self, **data):
5353
super().__init__(
54-
text=pretty_lenient_json(data), content_type=JSON_CONTENT_TYPE, headers=ACCESS_CONTROL_HEADERS,
54+
text=pretty_lenient_json(data),
55+
content_type=JSON_CONTENT_TYPE,
56+
headers=ACCESS_CONTROL_HEADERS,
5557
)
5658

5759

@@ -109,7 +111,8 @@ def get_arg(request, field, *, decoder: Callable[[str], Any] = int, default: Any
109111
return None if v is None else decoder(v)
110112
except ValueError:
111113
raise HTTPBadRequestJson(
112-
status='invalid_argument', details=f'"{field}" had an invalid value "{v}"',
114+
status='invalid_argument',
115+
details=f'"{field}" had an invalid value "{v}"',
113116
)
114117

115118

0 commit comments

Comments
 (0)