-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
414 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,15 @@ components: | |
example: | ||
message: 'Bad request' | ||
|
||
PermissionDenied: | ||
description: 'Permission denied' | ||
content: | ||
'application/json': | ||
schema: | ||
$ref: '#/components/schemas/Error' | ||
example: | ||
message: 'Permission denied' | ||
|
||
schemas: | ||
Error: | ||
type: object | ||
|
@@ -40,21 +49,73 @@ components: | |
name: | ||
type: string | ||
maxLength: 255 | ||
example: 'John Doe' | ||
designation: | ||
type: string | ||
example: 'Manager' | ||
team_name: | ||
type: string | ||
example: 'Sales' | ||
email: | ||
type: string | ||
format: email | ||
example: '[email protected]' | ||
profile_pic: | ||
type: string | ||
format: url | ||
example: 'https://cdn.example.com/images/dcd1674d3ddf42a59817202f.jpg' | ||
username: | ||
type: string | ||
example: 'john.doe' | ||
|
||
OneOnOneActionItem: | ||
type: object | ||
properties: | ||
id: | ||
type: integer | ||
example: 995296 | ||
state: | ||
type: boolean | ||
example: false | ||
content: | ||
type: string | ||
example: 'This is an action item' | ||
created_by: | ||
$ref: '#/components/schemas/User' | ||
|
||
OneOnOne: | ||
type: object | ||
properties: | ||
id: | ||
type: integer | ||
example: 261993 | ||
created_at: | ||
type: string | ||
format: date-time | ||
example: '2021-01-11T22:40:08+05:30Z' | ||
created_by: | ||
$ref: '#/components/schemas/User' | ||
user: | ||
$ref: '#/components/schemas/User' | ||
|
||
OneOnOneDetail: | ||
allOf: | ||
- $ref: '#/components/schemas/OneOnOne' | ||
- type: object | ||
properties: | ||
action_items: | ||
type: array | ||
items: | ||
- $ref: '#/components/schemas/OneOnOneActionItem' | ||
|
||
CreateOneOnOne: | ||
type: object | ||
properties: | ||
user: | ||
type: string | ||
|
||
paths: | ||
'/v1/users/_autocomplete': | ||
'/users/_autocomplete': | ||
get: | ||
summary: 'Autocomplete' | ||
responses: | ||
|
@@ -66,3 +127,66 @@ paths: | |
$ref: '#/components/schemas/User' | ||
'400': | ||
$ref: '#/components/responses/BadRequest' | ||
|
||
'/one_on_ones': | ||
get: | ||
summary: 'Get One on Ones' | ||
responses: | ||
'200': | ||
description: 'OK' | ||
content: | ||
'application/json': | ||
schema: | ||
type: array | ||
items: | ||
$ref: '#/components/schemas/OneOnOne' | ||
put: | ||
summary: 'Create one on one' | ||
requestBody: | ||
content: | ||
'application/json': | ||
schema: | ||
$ref: '#/components/schemas/CreateOneOnOne' | ||
responses: | ||
'201': | ||
description: 'Created' | ||
content: | ||
'application/json': | ||
schema: | ||
$ref: '#/components/schemas/OneOnOneDetail' | ||
'400': | ||
$ref: '#/components/responses/BadRequest' | ||
'403': | ||
$ref: '#/components/responses/PermissionDenied' | ||
|
||
|
||
'/one_on_ones/{id}': | ||
parameters: | ||
- in: path | ||
name: id | ||
schema: | ||
type: integer | ||
required: true | ||
get: | ||
summary: 'Get one on one by ID' | ||
responses: | ||
'200': | ||
description: 'OK' | ||
content: | ||
'application/json': | ||
schema: | ||
$ref: '#/components/schemas/OneOnOneDetail' | ||
'400': | ||
$ref: '#/components/responses/BadRequest' | ||
'403': | ||
$ref: '#/components/responses/PermissionDenied' | ||
|
||
delete: | ||
summary: 'Delete one on one by ID' | ||
responses: | ||
'204': | ||
description: 'OK' | ||
'400': | ||
$ref: '#/components/responses/BadRequest' | ||
'403': | ||
$ref: '#/components/responses/PermissionDenied' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .one_on_one import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from flask_login import current_user | ||
|
||
from snowflake.models import OneOnOne, User | ||
|
||
|
||
def can_view_one_on_one(one_on_one: OneOnOne, user: User = current_user): | ||
return user.id == one_on_one.user_id or user.id == one_on_one.created_by_id | ||
|
||
|
||
def can_delete_one_on_one(one_on_one: OneOnOne, user: User = current_user): | ||
return can_view_one_on_one(one_on_one, user) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
from . import users | ||
from . import notifications | ||
from . import one_on_ones | ||
from . import users |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
from datetime import datetime | ||
|
||
from flask import Blueprint, request | ||
from flask_login import login_required, current_user | ||
from marshmallow import ValidationError | ||
|
||
from .response import not_found, unauthorized, no_content, bad_request, validation_error | ||
from ... import acl | ||
from ...db import transaction, db | ||
from ...models import OneOnOne, OneOnOneActionItem | ||
from ...schemas.one_on_one import OneOnOneSchema, GetOneOnOneSchema, CreateOneOnOneSchema, OneOnOneActionItemSchema, \ | ||
CreateOrEditOneOnOneActionItemSchema | ||
|
||
blueprint = Blueprint('api.one_on_ones', __name__) | ||
|
||
one_on_one_schema = OneOnOneSchema() | ||
one_on_one_action_item_schema = OneOnOneActionItemSchema() | ||
get_one_on_one_schema = GetOneOnOneSchema() | ||
create_one_on_one_schema = CreateOneOnOneSchema() | ||
create_or_edit_one_on_one_action_item_schema = CreateOrEditOneOnOneActionItemSchema() | ||
|
||
|
||
@login_required | ||
@blueprint.route('', methods=['GET']) | ||
def list_all(): | ||
return one_on_one_schema.jsonify(OneOnOne.get_by_user(current_user), many=True) | ||
|
||
|
||
@login_required | ||
@blueprint.route('', methods=['PUT']) | ||
def create(): | ||
if not request.is_json(): | ||
return bad_request() | ||
|
||
try: | ||
one_on_one: OneOnOne = create_one_on_one_schema.load(request.json) | ||
one_on_one.created_by = current_user | ||
one_on_one.created_at = datetime.now() | ||
|
||
with transaction(): | ||
OneOnOne.create(one_on_one) | ||
|
||
return get_one_on_one_schema.jsonify(one_on_one) | ||
except ValidationError as e: | ||
return validation_error(e.messages) | ||
|
||
|
||
@login_required | ||
@blueprint.route('/<_id>', methods=['GET']) | ||
def get(_id: int): | ||
one_on_one = OneOnOne.get(_id) | ||
|
||
if not one_on_one: | ||
return not_found() | ||
|
||
if not acl.can_view_one_on_one(one_on_one): | ||
return unauthorized() | ||
|
||
return get_one_on_one_schema.jsonify(one_on_one) | ||
|
||
|
||
@login_required | ||
@blueprint.route('/<one_on_one_id>/action_items', methods=['GET']) | ||
def get_action_items(one_on_one_id: int): | ||
one_on_one = OneOnOne.get(one_on_one_id) | ||
|
||
if not one_on_one: | ||
return not_found() | ||
|
||
if not acl.can_view_one_on_one(one_on_one): | ||
return unauthorized() | ||
|
||
return one_on_one_action_item_schema.jsonify(one_on_one.action_items, many=True) | ||
|
||
|
||
@login_required | ||
@blueprint.route('/<one_on_one_id>/action_items/<action_item_id>', methods=['GET']) | ||
def get_action_item(one_on_one_id: int, action_item_id: int): | ||
one_on_one = OneOnOne.get(one_on_one_id) | ||
|
||
if not one_on_one: | ||
return not_found() | ||
|
||
if not acl.can_view_one_on_one(one_on_one): | ||
return unauthorized() | ||
|
||
action_item = OneOnOneActionItem.get(action_item_id) | ||
|
||
if not action_item: | ||
return not_found() | ||
|
||
if not action_item.one_on_one_id == one_on_one.id: | ||
return not_found() | ||
|
||
return one_on_one_action_item_schema.jsonify(action_item) | ||
|
||
|
||
@login_required | ||
@blueprint.route('/<one_on_one_id>/action_items/<action_item_id>', methods=['DELETE']) | ||
def delete_action_item(one_on_one_id: int, action_item_id: int): | ||
one_on_one = OneOnOne.get(one_on_one_id) | ||
|
||
if not one_on_one: | ||
return not_found() | ||
|
||
if not acl.can_view_one_on_one(one_on_one): | ||
return unauthorized() | ||
|
||
action_item = OneOnOneActionItem.get(action_item_id) | ||
|
||
if not action_item: | ||
return not_found() | ||
|
||
if not action_item.one_on_one_id == one_on_one.id: | ||
return not_found() | ||
|
||
with transaction(): | ||
db.session.remove(one_on_one) | ||
|
||
return no_content() | ||
|
||
|
||
@login_required | ||
@blueprint.route('/<one_on_one_id>/action_items', methods=['PUT']) | ||
def create_action_item(one_on_one_id: int): | ||
if not request.is_json(): | ||
return bad_request() | ||
|
||
one_on_one = OneOnOne.get(one_on_one_id) | ||
|
||
if not one_on_one: | ||
return not_found() | ||
|
||
if not acl.can_view_one_on_one(one_on_one): | ||
return unauthorized() | ||
|
||
try: | ||
action_item: OneOnOneActionItem = create_or_edit_one_on_one_action_item_schema.load(request.json) | ||
action_item.one_on_one = one_on_one | ||
action_item.created_by = current_user | ||
action_item.created_at = datetime.now() | ||
|
||
with transaction(): | ||
OneOnOneActionItem.create(action_item) | ||
|
||
return one_on_one_action_item_schema.jsonify(action_item) | ||
except ValidationError as e: | ||
return validation_error(e.messages) | ||
|
||
|
||
@login_required | ||
@blueprint.route('/<one_on_one_id>/action_items/<action_item_id>', methods=['PATCH']) | ||
def edit_action_item(one_on_one_id: int, action_item_id: int): | ||
if not request.is_json(): | ||
return bad_request() | ||
|
||
one_on_one = OneOnOne.get(one_on_one_id) | ||
|
||
if not one_on_one: | ||
return not_found() | ||
|
||
if not acl.can_view_one_on_one(one_on_one): | ||
return unauthorized() | ||
|
||
action_item = OneOnOneActionItem.get(action_item_id) | ||
|
||
try: | ||
action_item: OneOnOneActionItem = create_or_edit_one_on_one_action_item_schema.load(request.json, action_item) | ||
|
||
with transaction(): | ||
db.session.add(action_item) | ||
|
||
return one_on_one_action_item_schema.jsonify(action_item) | ||
except ValidationError as e: | ||
return validation_error(e.messages) | ||
|
||
|
||
@login_required | ||
@blueprint.route('/<_id>', methods=['DELETE']) | ||
def delete_one_on_one(_id: int): | ||
one_on_one = OneOnOne.get(_id) | ||
|
||
if not one_on_one: | ||
return not_found() | ||
|
||
if not acl.can_delete_one_on_one(one_on_one): | ||
return unauthorized() | ||
|
||
with transaction(): | ||
db.session.remove(one_on_one) | ||
|
||
return no_content() |
Oops, something went wrong.