Add team integration endpoints
- Add new endpoints for managing team integrations: - GET /id/<team_id>/integrations - POST /id/<team_id>/integrations/<integration_type> - DELETE /id/<team_id>/integrations/<integration_id> - PATCH /id/<team_id>/integrations/<integration_id> - Introduce schemas for TeamIntegration and TeamDiscordIntegration - Update models to include nullable webhook_urlmaster
parent
3cb9084a69
commit
8a00c53479
|
@ -1,8 +1,10 @@
|
||||||
|
#from typing import cast, override
|
||||||
from sqlalchemy.orm import mapped_column, relationship
|
from sqlalchemy.orm import mapped_column, relationship
|
||||||
from sqlalchemy.orm.attributes import Mapped
|
from sqlalchemy.orm.attributes import Mapped
|
||||||
from sqlalchemy.orm.properties import ForeignKey
|
from sqlalchemy.orm.properties import ForeignKey
|
||||||
from sqlalchemy.types import Integer, String
|
from sqlalchemy.types import Integer, String
|
||||||
import app_db
|
import app_db
|
||||||
|
import spec
|
||||||
|
|
||||||
|
|
||||||
class TeamIntegration(app_db.BaseModel):
|
class TeamIntegration(app_db.BaseModel):
|
||||||
|
@ -23,10 +25,35 @@ class TeamDiscordIntegration(TeamIntegration):
|
||||||
__tablename__ = "team_discord_integrations"
|
__tablename__ = "team_discord_integrations"
|
||||||
|
|
||||||
integration_id: Mapped[int] = mapped_column(ForeignKey("team_integrations.id"), primary_key=True)
|
integration_id: Mapped[int] = mapped_column(ForeignKey("team_integrations.id"), primary_key=True)
|
||||||
webhook_url: Mapped[str] = mapped_column(String(255))
|
webhook_url: Mapped[str] = mapped_column(String(255), nullable=True)
|
||||||
|
|
||||||
__mapper_args__ = {
|
__mapper_args__ = {
|
||||||
"polymorphic_identity": "team_discord_integrations",
|
"polymorphic_identity": "team_discord_integrations",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TeamIntegrationSchema(spec.BaseModel):
|
||||||
|
id: int
|
||||||
|
team_id: int
|
||||||
|
integration_type: str
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_model(cls, model: TeamIntegration):
|
||||||
|
if model.integration_type == "team_discord_integrations":
|
||||||
|
if isinstance(model, TeamDiscordIntegration):
|
||||||
|
return TeamDiscordIntegrationSchema._from_model_discord(model)
|
||||||
|
raise TypeError()
|
||||||
|
|
||||||
|
class TeamDiscordIntegrationSchema(TeamIntegrationSchema):
|
||||||
|
webhook_url: str
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _from_model_discord(cls, model: TeamDiscordIntegration):
|
||||||
|
assert model.integration_id != None
|
||||||
|
return cls(
|
||||||
|
id=model.integration_id,
|
||||||
|
team_id=model.team_id,
|
||||||
|
integration_type=model.integration_type,
|
||||||
|
webhook_url=model.webhook_url
|
||||||
|
)
|
||||||
|
|
||||||
from models.team import Team
|
from models.team import Team
|
||||||
|
|
|
@ -14,6 +14,7 @@ from models.player_team_availability import PlayerTeamAvailability
|
||||||
from models.player_team_role import PlayerTeamRole, RoleSchema
|
from models.player_team_role import PlayerTeamRole, RoleSchema
|
||||||
from models.team import Team, TeamSchema
|
from models.team import Team, TeamSchema
|
||||||
from models.team_invite import TeamInvite, TeamInviteSchema
|
from models.team_invite import TeamInvite, TeamInviteSchema
|
||||||
|
from models.team_integration import TeamDiscordIntegration, TeamDiscordIntegrationSchema, TeamIntegration, TeamIntegrationSchema
|
||||||
from middleware import assert_team_authority, requires_authentication, requires_team_membership
|
from middleware import assert_team_authority, requires_authentication, requires_team_membership
|
||||||
import models
|
import models
|
||||||
from spec import spec, BaseModel
|
from spec import spec, BaseModel
|
||||||
|
@ -561,3 +562,129 @@ def revoke_invite(player: Player, team_id: int, key: str, **kwargs):
|
||||||
db.session.delete(invite)
|
db.session.delete(invite)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return make_response({ }, 204)
|
return make_response({ }, 204)
|
||||||
|
|
||||||
|
@api_team.get("/id/<team_id>/integrations")
|
||||||
|
@spec.validate(
|
||||||
|
resp=Response(
|
||||||
|
HTTP_200=list[TeamIntegrationSchema],
|
||||||
|
HTTP_404=None,
|
||||||
|
),
|
||||||
|
operation_id="get_integrations"
|
||||||
|
)
|
||||||
|
@requires_authentication
|
||||||
|
def get_integrations(player: Player, team_id: int, **kwargs):
|
||||||
|
player_team = db.session.query(
|
||||||
|
PlayerTeam
|
||||||
|
).where(
|
||||||
|
PlayerTeam.player_id == player.steam_id
|
||||||
|
).where(
|
||||||
|
PlayerTeam.team_id == team_id
|
||||||
|
).one_or_none()
|
||||||
|
|
||||||
|
if not player_team:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
integrations = db.session.query(
|
||||||
|
TeamIntegration
|
||||||
|
).where(
|
||||||
|
TeamIntegration.team_id == team_id
|
||||||
|
).all()
|
||||||
|
|
||||||
|
def map_integration_to_schema(integration: TeamIntegration):
|
||||||
|
return TeamIntegrationSchema.from_model(
|
||||||
|
integration
|
||||||
|
).dict(by_alias=True)
|
||||||
|
|
||||||
|
return list(map(map_integration_to_schema, integrations))
|
||||||
|
|
||||||
|
@api_team.post("/id/<team_id>/integrations/<integration_type>")
|
||||||
|
@spec.validate(
|
||||||
|
resp=Response(
|
||||||
|
HTTP_200=TeamIntegrationSchema,
|
||||||
|
),
|
||||||
|
operation_id="create_integration"
|
||||||
|
)
|
||||||
|
@requires_authentication
|
||||||
|
@requires_team_membership
|
||||||
|
def create_integration(player_team: PlayerTeam, integration_type: str, **_):
|
||||||
|
assert_team_authority(player_team)
|
||||||
|
|
||||||
|
if integration_type == "discord":
|
||||||
|
integration = TeamDiscordIntegration()
|
||||||
|
integration.team_id = player_team.team_id
|
||||||
|
integration.webhook_url = ""
|
||||||
|
else:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
db.session.add(integration)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return TeamIntegrationSchema.from_model(
|
||||||
|
integration
|
||||||
|
).dict(by_alias=True), 200
|
||||||
|
|
||||||
|
@api_team.delete("/id/<team_id>/integrations/<integration_id>")
|
||||||
|
@spec.validate(
|
||||||
|
resp=Response(
|
||||||
|
HTTP_204=None,
|
||||||
|
),
|
||||||
|
operation_id="delete_integration"
|
||||||
|
)
|
||||||
|
def delete_integration(player_team: PlayerTeam, integration_id: int):
|
||||||
|
assert_team_authority(player_team)
|
||||||
|
|
||||||
|
integration = db.session.query(
|
||||||
|
TeamIntegration
|
||||||
|
).where(
|
||||||
|
TeamIntegration.team_id == player_team.team_id
|
||||||
|
).where(
|
||||||
|
TeamIntegration.id == integration_id
|
||||||
|
).one_or_none()
|
||||||
|
|
||||||
|
if not integration:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
db.session.delete(integration)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return make_response({ }, 204)
|
||||||
|
|
||||||
|
@api_team.patch("/id/<team_id>/integrations/<integration_id>")
|
||||||
|
@spec.validate(
|
||||||
|
resp=Response(
|
||||||
|
HTTP_200=TeamIntegrationSchema,
|
||||||
|
),
|
||||||
|
operation_id="update_integration"
|
||||||
|
)
|
||||||
|
def update_integration(
|
||||||
|
player_team: PlayerTeam,
|
||||||
|
integration_id: int,
|
||||||
|
json: TeamIntegrationSchema,
|
||||||
|
**_
|
||||||
|
):
|
||||||
|
assert_team_authority(player_team)
|
||||||
|
|
||||||
|
integration = db.session.query(
|
||||||
|
TeamIntegration
|
||||||
|
).where(
|
||||||
|
TeamIntegration.team_id == player_team.team_id
|
||||||
|
).where(
|
||||||
|
TeamIntegration.id == integration_id
|
||||||
|
).one_or_none()
|
||||||
|
|
||||||
|
if not integration:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
if isinstance(integration, TeamDiscordIntegration):
|
||||||
|
if isinstance(json, TeamDiscordIntegrationSchema):
|
||||||
|
integration.webhook_url = json.webhook_url
|
||||||
|
else:
|
||||||
|
abort(400)
|
||||||
|
else:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return TeamIntegrationSchema.from_model(
|
||||||
|
integration
|
||||||
|
).dict(by_alias=True), 200
|
||||||
|
|
Loading…
Reference in New Issue