Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • car-app/appwrite-functions
1 result
Show changes
Commits on Source (2)
Showing
with 455 additions and 184 deletions
import 'package:api/model/requesting_user_details.dart';
import 'package:lib/lib.dart';
import 'package:api/model/calendar_event.dart';
import 'package:api/model/team.dart';
import 'package:api/model/user.dart';
import 'package:lib/lib.dart';
class CalendarEventApiEndpoint extends CheckedDbApiEndpoint<CalendarEvent, CalendarEvent> {
final User requestingUser;
final Iterable<Team> requestingUserTeams;
class CalendarEventApiEndpoint extends DbApiEndpoint<CalendarEvent, CalendarEvent> {
final RequestingUserDetails requestingUser;
@override
Future<bool> Function(CalendarEvent) get createItemAllowed => _createItemAllowed;
@override
Future<bool> Function(CalendarEvent) get getItemAllowed => _getItemAllowed;
@override
Future<bool> Function(CalendarEvent, CalendarEvent) get updateItemAllowed => _updateItemAllowed;
@override
Future<bool> Function(CalendarEvent) get deleteItemAllowed => _deleteItemAllowed;
CalendarEventApiEndpoint({
required super.database,
required super.itemFromRequest,
required super.itemToResponse,
required this.requestingUser,
required this.requestingUserTeams,
});
@override
Future<CalendarEvent> create(CalendarEvent item) {
if (!requestingUser.teamIds.contains(item.teamId)){
throw UnauthorizedException();
}
if (requestingUser.userId != item.userId) {
throw UnauthorizedException();
}
return super.create(item);
Future<bool> _createItemAllowed(CalendarEvent item) {
return Future.value(
_isUserInTeam(item)
&& _isUserOwner(item)
);
}
@override
Future<CalendarEvent> getFromId(String id) async {
var item = await super.getFromId(id);
if(requestingUser.userId != item.userId) {
throw UnauthorizedException();
}
return item;
Future<bool> _getItemAllowed(CalendarEvent item) {
return Future.value(
_isUserInTeam(item)
);
}
@override
Stream<CalendarEvent> getFromQueries(Iterable<String> queries) async* {
await for(var queryResult in super.getFromQueries(queries)) {
if (requestingUser.userId == queryResult.userId) {
yield queryResult;
}
}
Future<bool> _updateItemAllowed(CalendarEvent item, CalendarEvent originalItem) {
return Future.value(
item.id == originalItem.id
&& _isUserInTeam(item)
&& _isUserOwner(item)
&& _isUserOwner(originalItem)
);
}
@override
Stream<CalendarEvent> getAll() async* {
await for(var item in super.getAll()) {
if(requestingUser.userId == item.userId) {
yield item;
}
}
Future<bool> _deleteItemAllowed(CalendarEvent item) {
return Future.value(
_isUserOwner(item)
);
}
@override
Future<CalendarEvent> update(CalendarEvent item) async {
var routeId = item.id;
if (routeId == null) {
throw RequiredArgumentMissing(RequestResponseVariables.idFieldName);
}
if (requestingUser.userId != item.userId) {
throw UnauthorizedException();
}
var dbItem = await getFromId(item.id!);
if (requestingUser.userId != dbItem.userId) {
throw UnauthorizedException();
}
bool _isUserOwner(CalendarEvent item) {
return requestingUser.id == item.userId;
}
return super.update(item);
bool _isUserInTeam(CalendarEvent item) {
return requestingUserTeams.any((team) => team.id == item.teamId);
}
}
import 'package:api/model/debt.dart';
import 'package:api/model/user.dart';
import 'package:api/service/debt.dart';
import 'package:api/model/requesting_user_details.dart';
import 'package:lib/lib.dart';
class DebtApiEndpoint extends ApiEndpoint {
final RequestingUserDetails requestingUser;
final User requestingUser;
final DebtService debtService;
final Map<String, dynamic> Function(Debt) itemToResponse;
......@@ -17,7 +17,7 @@ class DebtApiEndpoint extends ApiEndpoint {
@override
Future<Map<String, dynamic>> handleGet(context) async {
var items = await debtService.getDebt(requestingUser.userId).toList();
var items = await debtService.getDebt(requestingUser.id).where((e) => checkGetAllowed(e, requestingUser.id)).toList();
return listResponse(context, items, itemToResponse);
}
......@@ -32,4 +32,7 @@ class DebtApiEndpoint extends ApiEndpoint {
throw ApiActionForbiddenException("put", "debt");
}
bool checkGetAllowed(Debt debt, String userId) {
return debt.creditor == userId || debt.debtor == userId;
}
}
import 'dart:async';
import 'package:api/model/payment/driven_distance_distributed.dart';
import 'package:api/model/route.dart';
import 'package:api/model/team.dart';
import 'package:api/model/user.dart';
import 'package:lib/lib.dart';
class DrivenDistanceDistributedPaymentApiEndpoint extends CheckedDbApiEndpoint<DrivenDistanceDistributedPayment, DrivenDistanceDistributedPayment> {
final User requestingUser;
final Iterable<Team> requestingUserTeams;
final Future<Route> Function(String) getRouteFromId;
@override
Future<bool> Function(DrivenDistanceDistributedPayment) get createItemAllowed => _createItemAllowed;
@override
Future<bool> Function(DrivenDistanceDistributedPayment) get getItemAllowed => _getItemAllowed;
@override
Future<bool> Function(DrivenDistanceDistributedPayment, DrivenDistanceDistributedPayment) get updateItemAllowed => _updateItemAllowed;
@override
Future<bool> Function(DrivenDistanceDistributedPayment) get deleteItemAllowed => _deleteItemAllowed;
DrivenDistanceDistributedPaymentApiEndpoint({
required super.database,
required super.itemFromRequest,
required super.itemToResponse,
required this.requestingUser,
required this.requestingUserTeams,
required this.getRouteFromId,
});
Future<bool> _createItemAllowed(DrivenDistanceDistributedPayment item) async {
return _isUserOwner(item)
&& _isUserInTeam(item)
&& _hasAtLeastOneRoute(item)
&& await _areRoutesInSameTeam(item)
&& _isAmountOk(item);
}
Future<bool> _getItemAllowed(DrivenDistanceDistributedPayment item) {
return Future.value(
_isUserInTeam(item)
);
}
Future<bool> _updateItemAllowed(DrivenDistanceDistributedPayment item, DrivenDistanceDistributedPayment originalItem) async {
return item.id == originalItem.id
&& _isUserOwner(item)
&& _isUserOwner(originalItem)
&& _isUserInTeam(item)
&& _hasAtLeastOneRoute(item)
&& await _areRoutesInSameTeam(item)
&& _isAmountOk(item);
}
Future<bool> _deleteItemAllowed(DrivenDistanceDistributedPayment item) {
return Future.value(
_isUserOwner(item)
);
}
bool _isUserOwner(DrivenDistanceDistributedPayment item) {
return item.paidBy == requestingUser.id;
}
bool _isUserInTeam(DrivenDistanceDistributedPayment item) {
return requestingUserTeams.any((e) => e.id == item.id);
}
bool _hasAtLeastOneRoute(DrivenDistanceDistributedPayment item) {
return item.routeIds.isNotEmpty;
}
Future<bool> _areRoutesInSameTeam(DrivenDistanceDistributedPayment item) async {
if(item.routeIds.isEmpty) {
return true;
}
var routes = Stream.fromFutures(item.routeIds.map((e) => getRouteFromId(e)));
var teamToBeComparedTo = await routes.first;
return routes.every((e) => e.teamId == teamToBeComparedTo.teamId);
}
bool _isAmountOk(DrivenDistanceDistributedPayment item) {
return item.amount >= 0;
}
}
import 'dart:async';
import 'package:api/model/payment/equally_distributed.dart';
import 'package:api/model/team.dart';
import 'package:api/model/user.dart';
import 'package:lib/lib.dart';
class EquallyDistributedApiEndpoint extends CheckedDbApiEndpoint<EquallyDistributedPayment, EquallyDistributedPayment> {
final User requestingUser;
final Iterable<Team> requestingUserTeams;
@override
Future<bool> Function(EquallyDistributedPayment) get createItemAllowed => _createItemAllowed;
@override
Future<bool> Function(EquallyDistributedPayment) get getItemAllowed => _getItemAllowed;
@override
Future<bool> Function(EquallyDistributedPayment, EquallyDistributedPayment) get updateItemAllowed => _updateItemAllowed;
@override
Future<bool> Function(EquallyDistributedPayment) get deleteItemAllowed => _deleteItemAllowed;
EquallyDistributedApiEndpoint({
required super.database,
required super.itemFromRequest,
required super.itemToResponse,
required this.requestingUser,
required this.requestingUserTeams,
});
Future<bool> _createItemAllowed(EquallyDistributedPayment item) {
return Future.value(
_isUserOwner(item)
&& _isUserInTeam(item)
&& _isAmountOk(item)
);
}
Future<bool> _getItemAllowed(EquallyDistributedPayment item) {
return Future.value(
_isUserInTeam(item)
);
}
Future<bool> _updateItemAllowed(EquallyDistributedPayment item, EquallyDistributedPayment originalItem) {
return Future.value(
item.id == originalItem.id
&& _isUserOwner(item)
&& _isUserOwner(originalItem)
&& _isUserInTeam(item)
&& _isAmountOk(item)
);
}
Future<bool> _deleteItemAllowed(EquallyDistributedPayment item) {
return Future.value(
_isUserOwner(item)
);
}
bool _isUserOwner(EquallyDistributedPayment item) {
return item.paidBy == requestingUser.id;
}
bool _isUserInTeam(EquallyDistributedPayment item) {
return requestingUserTeams.any((team) => team.id == item.teamId);
}
bool _isAmountOk(EquallyDistributedPayment item) {
return item.amount >= 0;
}
}
import 'package:api/model/payment/user_to_user.dart';
import 'package:api/model/user.dart';
import 'package:lib/lib.dart';
class UserToUserPaymentApiEndpoint extends CheckedDbApiEndpoint<UserToUserPayment, UserToUserPayment> {
final User requestingUser;
@override
Future<bool> Function(UserToUserPayment) get createItemAllowed => _createItemAllowed;
@override
Future<bool> Function(UserToUserPayment) get getItemAllowed => _getItemAllowed;
@override
Future<bool> Function(UserToUserPayment, UserToUserPayment) get updateItemAllowed => _updateItemAllowed;
@override
Future<bool> Function(UserToUserPayment) get deleteItemAllowed => _deleteItemAllowed;
UserToUserPaymentApiEndpoint({
required super.database,
required super.itemFromRequest,
required super.itemToResponse,
required this.requestingUser,
});
Future<bool> _createItemAllowed(UserToUserPayment item) {
return Future.value(
_isUserPayer(item)
&& _isPayerNotPayee(item)
&& _isAmountOk(item)
);
}
Future<bool> _getItemAllowed(UserToUserPayment item) {
return Future.value(
_isUserPayer(item)
|| _isUserPayee(item)
);
}
Future<bool> _updateItemAllowed(UserToUserPayment item, UserToUserPayment originalItem) {
return Future.value(
item.id == originalItem.id
&& _isUserPayer(item)
&& _isUserPayer(originalItem)
&& _isPayerNotPayee(item)
&& _isAmountOk(item)
);
}
Future<bool> _deleteItemAllowed(UserToUserPayment item) {
return Future.value(
_isUserPayer(item)
);
}
bool _isUserPayer(UserToUserPayment item) {
return item.paidBy == requestingUser.id;
}
bool _isUserPayee(UserToUserPayment item) {
return item.paidTo == requestingUser.id;
}
bool _isPayerNotPayee(UserToUserPayment item) {
return item.paidBy != item.paidTo;
}
bool _isAmountOk(UserToUserPayment item) {
return item.amount >= 0;
}
}
......@@ -2,7 +2,11 @@ import 'package:lib/lib.dart';
import 'package:api/model/point.dart';
class PointApiEndpoint extends DbApiEndpoint<Point, Point> {
PointApiEndpoint({required super.database, required super.itemFromRequest, required super.itemToResponse});
PointApiEndpoint({
required super.database,
required super.itemFromRequest,
required super.itemToResponse,
});
@override
Stream<Point> getAll() {
......@@ -10,12 +14,12 @@ class PointApiEndpoint extends DbApiEndpoint<Point, Point> {
}
@override
Future<Map<String, dynamic>> handleDelete(context) {
Future<Point> delete(String id) {
throw ApiActionForbiddenException("delete", "point");
}
@override
Future<Map<String, dynamic>> handlePut(context) {
Future<Point> update(Point item) {
throw ApiActionForbiddenException("put", "point");
}
}
import 'package:api/model/requesting_user_details.dart';
import 'package:lib/lib.dart';
import 'package:api/model/route.dart';
import 'package:api/model/team.dart';
import 'package:api/model/user.dart';
import 'package:lib/lib.dart';
class RouteApiEndpoint extends DbApiEndpoint<Route, Route> {
final RequestingUserDetails requestingUser;
RouteApiEndpoint({required super.database, required super.itemFromRequest, required super.itemToResponse, required this.requestingUser});
class RouteApiEndpoint extends CheckedDbApiEndpoint<Route, Route> {
final User requestingUser;
final Iterable<Team> requestingUserTeams;
@override
Future<Route> create(Route item) {
if (!requestingUser.teamIds.contains(item.teamId)){
throw UnauthorizedException();
}
Future<bool> Function(Route) get createItemAllowed => _createItemAllowed;
if (requestingUser.userId != item.userId) {
throw UnauthorizedException();
}
@override
Future<bool> Function(Route) get getItemAllowed => _getItemAllowed;
return super.create(item);
}
@override
Future<bool> Function(Route, Route) get updateItemAllowed => _updateItemAllowed;
@override
Future<Route> getFromId(String id) async {
var item = await super.getFromId(id);
Future<bool> Function(Route) get deleteItemAllowed => _deleteItemAllowed;
if(requestingUser.userId != item.userId) {
throw UnauthorizedException();
}
RouteApiEndpoint({
required super.database,
required super.itemFromRequest,
required super.itemToResponse,
required this.requestingUser,
required this.requestingUserTeams,
});
return item;
Future<bool> _createItemAllowed(Route item) {
return Future.value(
_isUserInTeam(item)
&& _isUserOwner(item)
);
}
@override
Stream<Route> getFromQueries(Iterable<String> queries) async* {
await for(var queryResult in super.getFromQueries(queries)) {
if (requestingUser.userId == queryResult.userId) {
yield queryResult;
}
}
Future<bool> _getItemAllowed(Route item) {
return Future.value(
_isUserOwner(item)
);
}
@override
Stream<Route> getAll() async* {
await for(var item in super.getAll()) {
if(requestingUser.userId == item.userId) {
yield item;
}
}
Future<bool> _updateItemAllowed(Route item, Route originalItem) {
return Future.value(
item.id == originalItem.id
&& _isUserInTeam(item)
&& _isUserOwner(item)
&& _isUserOwner(originalItem)
);
}
@override
Future<Route> update(Route item) async {
var routeId = item.id;
if (routeId == null) {
throw RequiredArgumentMissing(RequestResponseVariables.idFieldName);
}
if (requestingUser.userId != item.userId) {
throw UnauthorizedException();
}
Future<bool> _deleteItemAllowed(Route item) {
return Future.value(
_isUserOwner(item)
);
}
var dbItem = await getFromId(item.id!);
if (requestingUser.userId != dbItem.userId) {
throw UnauthorizedException();
}
bool _isUserInTeam(Route item) {
return item.teamId != null ? requestingUserTeams.any((e) => e.id == item.teamId) : true;
}
return super.update(item);
bool _isUserOwner(Route item) {
return item.userId == requestingUser.id;
}
}
......@@ -19,10 +19,11 @@ class ScheduleApiEndpoint extends ApiEndpoint {
@override
Future<Map<String, dynamic>> handlePost(context) async {
if(trigger == "schedule") {
return context.res.send(DateTime.now().toIso8601String());
if(trigger != "schedule") {
throw ApiActionForbiddenException("POST", path);
}
throw ApiActionForbiddenException("POST", path);
return context.res.send(DateTime.now().toIso8601String());
}
@override
......
import 'package:api/model/requesting_user_details.dart';
import 'package:api/model/team.dart';
import 'package:api/service/team_service.dart';
import 'package:api/model/user.dart';
import 'package:lib/lib.dart';
class TeamApiEndpoint extends ApiEndpoint {
final TeamService teamService;
final User requestingUser;
final Stream<Team> Function(User) getTeamsOfUser;
final Map<String, dynamic> Function(Team) itemToResponse;
final RequestingUserDetails requestingUser;
TeamApiEndpoint({required this.teamService, required this.itemToResponse, required this.requestingUser});
TeamApiEndpoint({required this.requestingUser, required this.getTeamsOfUser, required this.itemToResponse});
@override
Future<Map<String, dynamic>> handleDelete(context) {
......@@ -17,7 +16,7 @@ class TeamApiEndpoint extends ApiEndpoint {
@override
Future<Map<String, dynamic>> handleGet(context) async {
var requestingUserTeams = await teamService.getTeamsOfUser(requestingUser.userId).toList();
var requestingUserTeams = await getTeamsOfUser(requestingUser).toList();
return listResponse(context, requestingUserTeams, itemToResponse);
}
......
import 'dart:convert';
import 'package:api/model/requesting_user_details.dart';
import 'package:api/service/team_service.dart';
import 'package:api/model/team.dart';
import 'package:api/model/user.dart';
import 'package:lib/lib.dart';
import 'package:api/service/user_service.dart';
class UserApiEndpoint extends ApiEndpoint {
final UserService userService;
final TeamService teamService;
final RequestingUserDetails requestingUser;
final User requestingUser;
final Future<User> Function(String) getUserFromId;
final Stream<Team> Function(User) getTeamsOfUser;
final Map<String, dynamic> Function(User) itemToResponse;
UserApiEndpoint({required this.userService, required this.teamService, required this.requestingUser, required this.itemToResponse});
UserApiEndpoint({required this.requestingUser, required this.getUserFromId, required this.getTeamsOfUser, required this.itemToResponse});
@override
Future<Map<String, dynamic>> handleDelete(context) {
......@@ -23,10 +21,11 @@ class UserApiEndpoint extends ApiEndpoint {
Future<Map<String, dynamic>> handleGet(context) async {
var requestedUserId = userIdFromContext(context);
var requestedUser = await userService.getUser(requestedUserId);
var requestedUserTeamIds = await teamService.getTeamsOfUser(requestedUserId).map((team) => team.teamId).toList();
var requestedUser = await getUserFromId(requestedUserId);
var requestedUserTeamIds = await getTeamsOfUser(requestedUser).map((e) => e.id).toList();
var requestingUserTeamIds = await getTeamsOfUser(requestingUser).map((e) => e.id).toList();
if(!requestingUser.teamIds.any((teamId) => requestedUserTeamIds.contains(teamId))) {
if(!requestedUserTeamIds.any((e) => requestingUserTeamIds.contains(e))) {
throw UnauthorizedException();
}
......
......@@ -7,7 +7,7 @@ extension EquallyDistributedPaymentRequestResponseConverter on EquallyDistribute
return (this as TeamPayment).toResponseData();
}
static EquallyDistributedPayment fromResponse(Map<String, dynamic> map) {
static EquallyDistributedPayment fromRequest(Map<String, dynamic> map) {
var teamPayment = TeamPaymentRequestResponseConverter.fromRequest(map);
return EquallyDistributedPayment(
id: teamPayment.id,
......
......@@ -4,14 +4,14 @@ import 'package:lib/lib.dart';
extension PaymentRequestResponseConverter on Payment {
static const String amountRequestResponseFieldName = "amount";
static const String paidByRequestResponseFieldName = "paidBy";
static const String timeAddedRequestResponseFieldName = "timeAdded";
static const String createdAtRequestResponseFieldName = "timeAdded";
Map<String, dynamic> toResponseData() {
return {
RequestResponseVariables.idFieldName: id,
amountRequestResponseFieldName: amount,
paidByRequestResponseFieldName: paidBy,
timeAddedRequestResponseFieldName: createdAt.toIso8601String(),
createdAtRequestResponseFieldName: createdAt.toIso8601String(),
};
}
}
......@@ -18,7 +18,7 @@ extension TeamPaymentRequestResponseConverter on TeamPayment {
id: getOptionalMapItem(RequestResponseVariables.idFieldName, map),
teamId: getRequiredMapItem(teamIdRequestResponseFieldName, map),
amount: getRequiredMapItem(PaymentRequestResponseConverter.amountRequestResponseFieldName, map),
createdAt: DateTime.parse(getRequiredMapItem(PaymentRequestResponseConverter.timeAddedRequestResponseFieldName, map)),
createdAt: DateTime.parse(getRequiredMapItem(PaymentRequestResponseConverter.createdAtRequestResponseFieldName, map)),
paidBy: getRequiredMapItem(PaymentRequestResponseConverter.paidByRequestResponseFieldName, map),
);
}
......
import 'package:api/converter/payment/request_response_converter.dart';
import 'package:api/model/payment/payment.dart';
import 'package:api/model/payment/user_to_user.dart';
import 'package:lib/lib.dart';
extension UserToUserPaymentRequestResponseConverter on UserToUserPayment {
static const String paidToRequestResponseFieldName = "paidTo";
Map<String, dynamic> toResponseData() {
return {
paidToRequestResponseFieldName: paidTo,
...(this as Payment).toResponseData()
};
}
static UserToUserPayment fromRequest(Map<String, dynamic> map) {
return UserToUserPayment(
id: getOptionalMapItem(RequestResponseVariables.idFieldName, map),
amount: getRequiredMapItem(PaymentRequestResponseConverter.amountRequestResponseFieldName, map),
createdAt: DateTime.parse(getRequiredMapItem(PaymentRequestResponseConverter.createdAtRequestResponseFieldName, map)),
paidBy: getRequiredMapItem(PaymentRequestResponseConverter.paidByRequestResponseFieldName, map),
paidTo: getRequiredMapItem(paidToRequestResponseFieldName, map)
);
}
}
......@@ -6,8 +6,8 @@ extension TeamRequestResponseConverter on Team {
Map<String, dynamic> toResponseData() {
return {
teamIdResponseFieldName: teamId,
teamNameResponseFieldName: teamName,
teamIdResponseFieldName: id,
teamNameResponseFieldName: name,
};
}
}
import 'dart:async';
import 'dart:io';
import 'package:api/api_endpoint/calendar_event.dart';
import 'package:api/api_endpoint/payment/driven_distance_distributed.dart';
import 'package:api/api_endpoint/payment/equally_distributed.dart';
import 'package:api/api_endpoint/payment/user_to_user.dart';
import 'package:api/converter/payment/user_to_user_payment.dart/request_response_converter.dart';
import 'package:api/database/calendar_event.dart';
import 'package:api/converter/calendar_event/db_converter.dart';
import 'package:api/converter/calendar_event/request_response_converter.dart';
......@@ -17,6 +21,8 @@ import 'package:api/converter/route/request_response_converter.dart';
import 'package:api/converter/team/request_response_converter.dart';
import 'package:api/converter/user/request_response_converter.dart';
import 'package:api/api_endpoint/debt.dart';
import 'package:api/model/team.dart';
import 'package:api/model/user.dart';
import 'package:api/service/debt.dart';
import 'package:api/database/payment/driven_distance_distributed.dart';
import 'package:api/database/payment/equally_distributed.dart';
......@@ -24,8 +30,8 @@ import 'package:api/database/payment/user_to_user.dart';
import 'package:api/model/payment/driven_distance_distributed.dart';
import 'package:api/model/payment/equally_distributed.dart';
import 'package:api/model/payment/user_to_user.dart';
import 'package:api/model/requesting_user_details.dart';
import 'package:api/api_endpoint/team.dart';
import 'package:api/service/membership_service.dart';
import 'package:api/service/team_service.dart';
import 'package:lib/lib.dart';
import 'package:api/api_endpoint/point.dart';
......@@ -44,6 +50,7 @@ const String teamApiEndpoint = "/team";
const String userApiPath = "/user";
const String drivenDistanceDistributedPaymentApiEndpoint = "/payment/team/drivendistance";
const String equallyDistributedPaymentApiEndpoint = "/payment/team/equal";
const String userToUserPaymentApiEndpoint = "/payment/user";
const String debtApiEndpoint = "/debt";
Future<dynamic> main(final context) async {
......@@ -103,13 +110,15 @@ Future<dynamic> main(final context) async {
);
var teamService = TeamService(host: host, projectId: projectId, apiKey: apiKey);
var userService = UserService(host: host, projectId: projectId, apiKey: apiKey);
var membershipService = MembershipService(host: host, projectId: projectId, apiKey: apiKey, teamService: teamService, userService: userService);
var debtService = DebtService(
getMembershipsByTeamId: membershipService.getTeamMemberships,
getRouteById: routeDatabase.get,
getTeamById: teamService.getTeam,
getUserToUserPayments: (userId) => getUserToUserPayments(userId, userToUserPaymentDatabase),
getEquallyDistributedPayments: (userId) => getEquallyDistributedPayments(userId, teamService, equallyDistributedPaymentDatabase),
getDrivenDistanceDistributedPayments: (userId) => getDrivenDistanceDistributedPayments(userId, teamService, drivenDistanceDistributedPaymentDatabase),
getEquallyDistributedPayments: (userId) => getEquallyDistributedPayments(userId, membershipService, equallyDistributedPaymentDatabase),
getDrivenDistanceDistributedPayments: (userId) => getDrivenDistanceDistributedPayments(userId, membershipService, drivenDistanceDistributedPaymentDatabase),
);
ApiEndpoint apiEndpoint;
......@@ -127,69 +136,92 @@ Future<dynamic> main(final context) async {
break;
case routeApiPath:
var requestingUser = await getRequestingUser(context, teamService);
var requestingUser = await getRequestingUser(context, userService);
var requestingUserTeams = await getUserTeams(requestingUser.id, membershipService).toList();
apiEndpoint = RouteApiEndpoint(
database: routeDatabase,
requestingUser: requestingUser,
itemFromRequest: (m) => RouteRequestResponseConverter.fromRequest(m, requestingUser.userId),
requestingUserTeams: requestingUserTeams,
itemFromRequest: (m) => RouteRequestResponseConverter.fromRequest(m, requestingUser.id),
itemToResponse: (r) => r.toResponseData(),
);
break;
case teamApiEndpoint:
var requestingUser = await getRequestingUser(context, teamService);
var requestingUser = await getRequestingUser(context, userService);
apiEndpoint = TeamApiEndpoint(
teamService: teamService,
requestingUser: requestingUser,
getTeamsOfUser: (user) => getUserTeams(user.id, membershipService),
itemToResponse: (e) => e.toResponseData(),
);
break;
case calendarEventApiPath:
var requestingUser = await getRequestingUser(context, teamService);
var requestingUser = await getRequestingUser(context, userService);
var requestingUserTeams = await getUserTeams(requestingUser.id, membershipService).toList();
apiEndpoint = CalendarEventApiEndpoint(
database: calendarEventDatabase,
itemFromRequest: (m) => CalendarEventRequestResponseConverter.fromRequest(m, requestingUser.userId),
itemFromRequest: (m) => CalendarEventRequestResponseConverter.fromRequest(m, requestingUser.id),
itemToResponse: (ce) => ce.toResponseData(),
requestingUser: requestingUser
requestingUser: requestingUser,
requestingUserTeams: requestingUserTeams,
);
break;
case userApiPath:
var requestingUser = await getRequestingUser(context, teamService);
var requestingUser = await getRequestingUser(context, userService);
apiEndpoint = UserApiEndpoint(
userService: UserService(host: host, projectId: projectId, apiKey: apiKey),
teamService: teamService,
requestingUser: requestingUser,
getTeamsOfUser: (user) => getUserTeams(user.id, membershipService),
getUserFromId: userService.getUser,
itemToResponse: (e) => e.toResponseData(),
);
break;
case drivenDistanceDistributedPaymentApiEndpoint:
apiEndpoint = DbApiEndpoint<DrivenDistanceDistributedPayment, DrivenDistanceDistributedPayment>( // TODO
var requestingUser = await getRequestingUser(context, userService);
apiEndpoint = DrivenDistanceDistributedPaymentApiEndpoint(
database: drivenDistanceDistributedPaymentDatabase,
itemFromRequest: DrivenDistanceDistributedPaymentRequestResponseConverter.fromRequest,
itemToResponse: (e) => e.toResponseData(),
requestingUser: requestingUser,
requestingUserTeams: await getUserTeams(requestingUser.id, membershipService).toList(),
getRouteFromId: routeDatabase.get
);
break;
case equallyDistributedPaymentApiEndpoint:
apiEndpoint = DbApiEndpoint<EquallyDistributedPayment, EquallyDistributedPayment>( // TODO
var requestingUser = await getRequestingUser(context, userService);
apiEndpoint = EquallyDistributedApiEndpoint(
database: equallyDistributedPaymentDatabase,
itemFromRequest: EquallyDistributedPaymentRequestResponseConverter.fromResponse,
requestingUser: requestingUser,
requestingUserTeams: await getUserTeams(requestingUser.id, membershipService).toList(),
itemFromRequest: EquallyDistributedPaymentRequestResponseConverter.fromRequest,
itemToResponse: (e) => e.toResponseData(),
);
break;
case userToUserPaymentApiEndpoint:
var requestingUser = await getRequestingUser(context, userService);
apiEndpoint = UserToUserPaymentApiEndpoint(
database: userToUserPaymentDatabase,
requestingUser: requestingUser,
itemFromRequest: UserToUserPaymentRequestResponseConverter.fromRequest,
itemToResponse: (e) => e.toResponseData(),
);
break;
case debtApiEndpoint:
var requestingUser = await getRequestingUser(context, teamService);
var requestingUser = await getRequestingUser(context, userService);
apiEndpoint = DebtApiEndpoint(
debtService: debtService,
itemToResponse: (e) => e.toResponseData(),
requestingUser: requestingUser,
);
break;
default:
throw HttpException("Path $requestPath not found", uri: Uri.parse(context.req.url));
......@@ -199,24 +231,25 @@ Future<dynamic> main(final context) async {
return requestHandler.handleRequest(context);
}
Future<RequestingUserDetails> getRequestingUser(final context, TeamService teamService) async {
Future<User> getRequestingUser(final context, UserService userService) async {
final userId = AppwriteVariables.userId(context);
return RequestingUserDetails(
userId: userId,
teamIds: await teamService.getTeamsOfUser(userId).map((e) => e.teamId).toList(),
);
return userService.getUser(userId);
}
Stream<Team> getUserTeams(String userId, MembershipService membershipService) {
return membershipService.getUserMemberships(userId).map((e) => e.team);
}
Stream<UserToUserPayment> getUserToUserPayments(String userId, UserToUserPaymentDatabase userToUserPaymentDatabase) {
return userToUserPaymentDatabase.getAll().where((e) => e.paidBy == userId || e.paidTo == userId);
}
Stream<EquallyDistributedPayment> getEquallyDistributedPayments(String userId, TeamService teamService, EquallyDistributedPaymentDatabase equallyDistributedPaymentDatabase) async* {
var userTeamIds = await teamService.getTeamsOfUser(userId).map((e) => e.teamId).toList();
Stream<EquallyDistributedPayment> getEquallyDistributedPayments(String userId, MembershipService membershipService, EquallyDistributedPaymentDatabase equallyDistributedPaymentDatabase) async* {
var userTeamIds = await membershipService.getUserMemberships(userId).map((e) => e.team.id).toList();
yield* equallyDistributedPaymentDatabase.getAll().where((e) => userTeamIds.contains(e.teamId)); // Would be nice with queries, but appwrite does not support nested queries
}
Stream<DrivenDistanceDistributedPayment> getDrivenDistanceDistributedPayments(String userId, TeamService teamService, DrivenDistanceDistributedPaymentDatabase drivenDistanceDistributedPaymentDatabase) async* {
var userTeamIds = await teamService.getTeamsOfUser(userId).map((e) => e.teamId).toList();
Stream<DrivenDistanceDistributedPayment> getDrivenDistanceDistributedPayments(String userId, MembershipService membershipService, DrivenDistanceDistributedPaymentDatabase drivenDistanceDistributedPaymentDatabase) async* {
var userTeamIds = await membershipService.getUserMemberships(userId).map((e) => e.team.id).toList();
yield* drivenDistanceDistributedPaymentDatabase.getAll().where((e) => userTeamIds.contains(e.teamId)); // Would be nice with queries, but appwrite does not support nested queries
}
class AppwriteUser {
final String id;
final String email;
final String name;
final bool isEnabled;
AppwriteUser({required this.id, required this.email, required this.name, required this.isEnabled});
}
import 'package:api/model/appwrite_user.dart';
import 'package:api/model/team.dart';
import 'package:api/model/user.dart';
class Membership {
final AppwriteUser user;
final User user;
final Team team;
final DateTime joinedAt;
Membership({required this.user, required this.joinedAt});
Membership({required this.user, required this.team, required this.joinedAt});
}
class RequestingUserDetails {
final String userId;
final Iterable<String> teamIds;
RequestingUserDetails({required this.userId, required this.teamIds});
}
import 'package:api/model/membership.dart';
class Team {
final String teamId;
final String teamName;
final Iterable<Membership> memberships;
final String id;
final String name;
Team({required this.teamId, required this.teamName, required this.memberships});
Team({required this.id, required this.name});
}