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 (8)
Showing
with 300 additions and 38 deletions
import 'package:lib/lib.dart';
import 'package:point/calendar_event/calendar_event_database.dart';
import 'package:point/calendar_event/models/calendar_event_db_model.dart';
import 'package:point/calendar_event/models/calendar_event_response.dart';
class CalendarEventApiEndpoint extends DbApiEndpoint<CalendarEventDbModel, CalendarEventResponse> {
static const String path = "/calendar";
CalendarEventApiEndpoint({required super.requestingUser, required String host, required String projectId, required String apiKey, required Future<User> Function(String) getUser}) :
super(
database: CalendarEventDatabase(host: host, projectId: projectId, apiKey: apiKey, getUser: getUser),
itemGenerator: (m) => CalendarEventDbModel.fromRequest(m, requestingUser.userId),
);
}
import 'package:lib/lib.dart';
import 'package:point/calendar_event/models/calendar_event_db_model.dart';
import 'package:point/calendar_event/models/calendar_event_response.dart';
class CalendarEventDatabase extends BaseDatabase<CalendarEventDbModel, CalendarEventResponse> {
@override
String get collectionId => "6619bc4edf8000989821";
@override
String get databaseId => "65fddef523b653ce0952";
CalendarEventDatabase({required super.host, required super.projectId, required super.apiKey, required Future<User> Function(String) getUser}) :
super(
itemFromDbMap: (m) async => CalendarEventResponse.fromDbData(m, await getUser(m[CalendarEventDbModel.userIdDbFieldName])),
);
@override
Future<DbResponse<CalendarEventResponse>> create(DbRequest<CalendarEventDbModel> request) {
if(!request.requestingUser.teamIds.contains(request.item.teamId)) {
throw UnauthorizedException();
}
return super.create(request);
}
@override
Future<DbResponse<CalendarEventResponse>> get(DbRequest<String> request) async {
var response = await super.get(request);
if(!request.requestingUser.teamIds.contains(response.item.teamId)) {
throw UnauthorizedException();
}
return response;
}
@override
Stream<DbResponse<CalendarEventResponse>> getFromQueries(DbRequest<Iterable<String>> request) async* {
await for(var queryResult in super.getFromQueries(request)) {
if(request.requestingUser.teamIds.contains(queryResult.item.teamId)) {
yield queryResult;
}
}
}
@override
Stream<DbResponse<CalendarEventResponse>> getAll(DbRequest request) async* {
await for(var response in super.getAll(request)) {
if(request.requestingUser.teamIds.contains(response.item.teamId)) {
yield response;
}
}
}
@override
Future<DbResponse<CalendarEventResponse>> update(DbRequest<CalendarEventDbModel> request) async {
var eventId = request.item.id;
if (eventId == null) {
throw RequiredArgumentMissing(RequestResponseVariables.idFieldName);
}
var response = await get(DbRequest(item: eventId, requestingUser: request.requestingUser));
if (response.item.user.id != request.requestingUser.userId) {
throw UnauthorizedException();
}
return super.update(request);
}
@override
Future<DbResponse<CalendarEventResponse>> delete(DbRequest<String> request) async {
var response = await get(request);
if(response.item.user.id != request.requestingUser.userId) {
throw UnauthorizedException();
}
return super.delete(request);
}
}
import 'package:lib/lib.dart';
class CalendarEvent {
static const teamIdDbFieldName = "teamId";
static const titleDbFieldName = "title";
static const descriptionDbFieldName = "description";
static const startDbFieldName = "start";
static const endDbFieldName = "end";
static const userIdRequestResponseFieldName = "userId";
static const teamIdRequestResponseFieldName = "teamId";
static const titleRequestResponseFieldName = "title";
static const descriptionRequestResponseFieldName = "description";
static const startRequestResponseFieldName = "start";
static const endRequestResponseFieldName = "end";
final String? _id;
final String _teamId;
final String _title;
final String? _description;
final DateTime _start;
final DateTime _end;
String? get id => _id;
Permissions? get permissions => null;
String get teamId => _teamId;
String get title => _title;
String? get description => _description;
DateTime get start => _start;
DateTime get end => _end;
CalendarEvent({String? id, required String teamId, required String title, String? description, required DateTime start, required DateTime end}) :
_id = id,
_teamId = teamId,
_title = title,
_description = description,
_start = start,
_end = end;
}
import 'package:lib/lib.dart';
import 'package:point/calendar_event/models/calendar_event.dart';
class CalendarEventDbModel extends CalendarEvent implements DbModel {
static const userIdDbFieldName = "userId";
final String _userId;
String get userId => _userId;
CalendarEventDbModel({ required String userId, super.id, required super.teamId, required super.title, super.description, required super.start, required super.end}) :
_userId = userId;
@override
Map<String, dynamic> toDbData() {
return {
userIdDbFieldName: userId,
CalendarEvent.teamIdDbFieldName: teamId,
CalendarEvent.titleDbFieldName: title,
CalendarEvent.descriptionDbFieldName: description,
CalendarEvent.startDbFieldName: start.toIso8601String(),
CalendarEvent.endDbFieldName: end.toIso8601String(),
};
}
factory CalendarEventDbModel.fromRequest(Map<String, dynamic> map, String userId) {
return CalendarEventDbModel(
id: getOptionalMapItem(RequestResponseVariables.idFieldName, map),
userId: userId,
teamId: getRequiredMapItem(CalendarEvent.teamIdRequestResponseFieldName, map),
title: getRequiredMapItem(CalendarEvent.titleRequestResponseFieldName, map),
description: getOptionalMapItem(CalendarEvent.descriptionRequestResponseFieldName, map),
start: DateTime.parse(getRequiredMapItem(CalendarEvent.startRequestResponseFieldName, map)),
end: DateTime.parse(getRequiredMapItem(CalendarEvent.endRequestResponseFieldName, map)),
);
}
}
import 'package:lib/lib.dart';
import 'package:point/calendar_event/models/calendar_event.dart';
class CalendarEventResponse extends CalendarEvent implements ResponseModel {
static const String userRequestResponseFieldName = 'user';
final User _user;
User get user => _user;
CalendarEventResponse({required User user, super.id, required super.teamId, required super.title, super.description, required super.start, required super.end}) :
_user = user;
@override
Map<String, dynamic> toResponseData() {
return {
RequestResponseVariables.idFieldName: id,
userRequestResponseFieldName: user.toResponseData(),
CalendarEvent.teamIdRequestResponseFieldName: teamId,
CalendarEvent.titleRequestResponseFieldName: title,
CalendarEvent.descriptionRequestResponseFieldName: description,
CalendarEvent.startRequestResponseFieldName: start.toIso8601String(),
CalendarEvent.endRequestResponseFieldName: end.toIso8601String(),
};
}
factory CalendarEventResponse.fromDbData(Map<String, dynamic> map, User user) {
return CalendarEventResponse(
id: getOptionalMapItem(DatabaseVariables.idColumnName, map),
user: user,
teamId: getRequiredMapItem(CalendarEvent.teamIdDbFieldName, map),
title: getRequiredMapItem(CalendarEvent. titleDbFieldName, map),
description: getOptionalMapItem(CalendarEvent.descriptionDbFieldName, map),
start: DateTime.parse(getRequiredMapItem(CalendarEvent.startDbFieldName, map)),
end: DateTime.parse(getRequiredMapItem(CalendarEvent.endDbFieldName, map)),
);
}
}
import 'dart:async';
import 'dart:io';
import 'package:point/calendar_event/calendar_event_api_endpoint.dart';
import 'package:point/membership/membership_api_endpoint.dart';
import 'package:point/membership/membership_service.dart';
import 'package:point/point/point_api_endpoint.dart';
......@@ -35,6 +36,12 @@ Future<dynamic> main(final context) async {
var membershipService = getMembershipService(context, host, projectId, apiKey);
apiEndpoint = MembershipApiEndpoint(membershipService: membershipService);
case CalendarEventApiEndpoint.path:
var membershipService = getMembershipService(context, host, projectId, apiKey);
var requestingUser = await getRequestingUser(context, membershipService);
var userHelper = UserHelper(host: host, projectId: projectId, apiKey: apiKey);
apiEndpoint = CalendarEventApiEndpoint(requestingUser: requestingUser, host: host, projectId: projectId, apiKey: apiKey, getUser: userHelper.userFromId);
default:
throw HttpException("Path $requestPath not found", uri: Uri.parse(context.req.url));
}
......
import 'dart:convert';
import 'package:lib/lib.dart';
import 'package:point/membership/membership_service.dart';
import 'package:point/membership/team.dart';
class MembershipApiEndpoint extends ApiEndpoint {
class MembershipApiEndpoint extends ApiEndpoint<Team> {
static const String path = "/membership";
MembershipService _membershipService;
final MembershipService _membershipService;
MembershipApiEndpoint({required MembershipService membershipService}) :
_membershipService = membershipService;
......@@ -19,8 +18,8 @@ class MembershipApiEndpoint extends ApiEndpoint {
@override
Future<Map<String, dynamic>> handleGet(context) async {
var memberships = await _membershipService.getMemberships().toList();
var response = memberships.map((e) => e.toResponse()).toList();
return context.res.send(jsonEncode(response));
return listResponse(context, memberships);
}
@override
......
......@@ -3,7 +3,7 @@ import 'package:lib/lib.dart';
import 'package:point/membership/team.dart';
class MembershipService extends ClientFunction {
String _userId;
final String _userId;
MembershipService({required super.host, required super.projectId, required super.apiKey, required String userId}) :
_userId = userId;
......
class Team {
import 'package:lib/lib.dart';
class Team implements ResponseModel {
static const String teamIdResponseFieldName = "teamId";
static const String teamNameResponseFieldName = "teamName";
......@@ -11,8 +13,9 @@ class Team {
Team({required String teamId, required String teamName}) :
_teamId = teamId,
_teamName = teamName;
Map<String, dynamic> toResponse() {
@override
Map<String, dynamic> toResponseData() {
return {
teamIdResponseFieldName: teamId,
teamNameResponseFieldName: teamName,
......
import 'package:lib/lib.dart';
class Point implements DbModel {
class Point implements DbModel, ResponseModel {
static const String latitudeDbFieldName = "latitude";
static const String longitudeDbFieldName = "longitude";
static const String latitudeRequestResponseFieldName = "latitude";
......
......@@ -2,7 +2,7 @@ import 'package:lib/lib.dart';
import 'package:point/point/point.dart';
import 'package:point/point/point_database.dart';
class PointApiEndpoint extends DbApiEndpoint {
class PointApiEndpoint extends DbApiEndpoint<Point, Point> {
static const String path = "/point";
PointApiEndpoint({required super.requestingUser, required String host, required String projectId, required String apiKey}) :
......
......@@ -2,7 +2,7 @@ import 'package:dart_appwrite/dart_appwrite.dart';
import 'package:lib/lib.dart';
import 'package:point/point/point.dart';
class PointDatabase extends BaseDatabase<Point> {
class PointDatabase extends BaseDatabase<Point, Point> {
@override
String get databaseId => "65fddef523b653ce0952";
......@@ -10,7 +10,7 @@ class PointDatabase extends BaseDatabase<Point> {
String get collectionId => "65fddefc7f63cb43b15b";
PointDatabase({required super.host, required super.projectId, required super.apiKey}) :
super(itemFromDbMap: Point.fromDbData);
super(itemFromDbMap: (m) async => Point.fromDbData(m));
@override
Future<DbResponse<Point>> create(DbRequest<Point> request) async {
......
import 'package:lib/lib.dart';
import 'package:point/point/point.dart';
class Route implements DbModel {
class Route implements DbModel, ResponseModel {
static const String userIdDbFieldName = "userId";
static const String teamIdDbFieldName = "teamId";
static const String pointsDbFieldName = "points";
......
......@@ -4,7 +4,7 @@ import 'package:lib/lib.dart';
import 'package:point/route/route.dart';
import 'package:point/route/route_database.dart';
class RouteApiEndpoint extends DbApiEndpoint<Route> {
class RouteApiEndpoint extends DbApiEndpoint<Route, Route> {
static const String path = "/route";
RouteApiEndpoint({required super.requestingUser, required String host, required String projectId, required String apiKey}) :
......
......@@ -3,7 +3,7 @@ import 'package:point/point/point.dart';
import 'package:point/point/point_database.dart';
import 'package:point/route/route.dart';
class RouteDatabase extends BaseDatabase<Route> {
class RouteDatabase extends BaseDatabase<Route, Route> {
final PointDatabase _pointDatabase;
@override
......@@ -14,7 +14,7 @@ class RouteDatabase extends BaseDatabase<Route> {
RouteDatabase({required super.host, required super.projectId, required super.apiKey}) :
_pointDatabase = PointDatabase(host: host, projectId: projectId, apiKey: apiKey),
super(itemFromDbMap: Route.fromDbData);
super(itemFromDbMap: (m) async => Route.fromDbData(m));
@override
Future<DbResponse<Route>> create(DbRequest<Route> request) async {
......@@ -33,7 +33,7 @@ class RouteDatabase extends BaseDatabase<Route> {
id: request.item.id,
points: points,
userId: request.item.userId,
teamId: request.item.userId
teamId: request.item.teamId,
),
requestingUser: request.requestingUser,
);
......@@ -60,6 +60,15 @@ class RouteDatabase extends BaseDatabase<Route> {
}
}
@override
Stream<DbResponse<Route>> getAll(DbRequest request) async* {
await for(var response in super.getAll(request)) {
if(request.requestingUser.userId == response.item.userId) {
yield response;
}
}
}
@override
Future<DbResponse<Route>> update(DbRequest<Route> request) async {
var routeId = request.item.id;
......
......@@ -20,3 +20,6 @@ export 'src/exceptions/required_argument_missing.dart';
export 'src/interface/api_endpoint.dart';
export 'src/db_api_endpoint.dart';
export 'src/exceptions/db_action_forbidden.dart';
export 'src/interface/response_model.dart';
export 'src/models/user.dart';
export 'src/utils/user_helper.dart';
......@@ -2,15 +2,16 @@ import 'dart:async';
import 'package:dart_appwrite/dart_appwrite.dart';
import 'package:dart_appwrite/models.dart' as appwrite_models;
import 'package:lib/src/interface/response_model.dart';
import 'package:lib/src/request_response/db_request.dart';
import 'package:lib/src/request_response/db_response.dart';
import 'package:lib/src/exceptions/id_null.dart';
import 'package:lib/src/interface/client_function.dart';
import 'package:lib/src/interface/db_model.dart';
abstract class BaseDatabase<T extends DbModel> extends ClientFunction {
abstract class BaseDatabase<T extends DbModel, T1 extends ResponseModel> extends ClientFunction {
static const String itemDataField = "data";
final T Function(Map<String, dynamic>) itemFromDbMap;
final Future<T1> Function(Map<String, dynamic>) itemFromDbMap;
late final Databases databases;
String get databaseId;
......@@ -20,33 +21,33 @@ abstract class BaseDatabase<T extends DbModel> extends ClientFunction {
databases = Databases(client);
}
Future<DbResponse<T>> create(DbRequest<T> request) async {
Future<DbResponse<T1>> create(DbRequest<T> request) async {
var id = request.item.id ?? ID.unique();
var document = await databases.createDocument(databaseId: databaseId, collectionId: collectionId, documentId: id, data: request.item.toDbData(), permissions: request.item.permissions?.dbPermissions);
return _responseFromDocument(document);
}
Future<DbResponse<T>> get(DbRequest<String> request) async {
Future<DbResponse<T1>> get(DbRequest<String> request) async {
var document = await databases.getDocument(databaseId: databaseId, collectionId: collectionId, documentId: request.item);
return _responseFromDocument(document);
}
Stream<DbResponse<T>> getFromQueries(DbRequest<Iterable<String>> request) async* {
Stream<DbResponse<T1>> getFromQueries(DbRequest<Iterable<String>> request) async* {
var queryResult = await databases.listDocuments(databaseId: databaseId, collectionId: collectionId, queries: request.item.toList());
for (var document in queryResult.documents) {
yield _responseFromDocument(document);
yield await _responseFromDocument(document);
}
}
Stream<DbResponse<T>> getAll(DbRequest request) async* {
Stream<DbResponse<T1>> getAll(DbRequest request) async* {
var queryResults = getFromQueries(DbRequest(item: [], requestingUser: request.requestingUser));
await for (var t in queryResults) {
yield t;
}
}
Future<DbResponse<T>> update(DbRequest<T> request) async {
Future<DbResponse<T1>> update(DbRequest<T> request) async {
var id = request.item.id;
if (id == null) {
throw IdNullException(request.item);
......@@ -55,13 +56,13 @@ abstract class BaseDatabase<T extends DbModel> extends ClientFunction {
return _responseFromDocument(document);
}
Future<DbResponse<T>> delete(DbRequest<String> request) async {
Future<DbResponse<T1>> delete(DbRequest<String> request) async {
var itemToDelete = await get(request);
await databases.deleteDocument(databaseId: databaseId, collectionId: collectionId, documentId: request.item);
return itemToDelete;
}
DbResponse<T> _responseFromDocument(appwrite_models.Document document) {
return DbResponse(item: itemFromDbMap(document.toMap()[itemDataField]));
Future<DbResponse<T1>> _responseFromDocument(appwrite_models.Document document) async {
return DbResponse(item: await itemFromDbMap(document.toMap()[itemDataField]));
}
}
......@@ -3,13 +3,14 @@ import 'dart:convert';
import 'package:lib/src/base_database.dart';
import 'package:lib/src/interface/api_endpoint.dart';
import 'package:lib/src/interface/db_model.dart';
import 'package:lib/src/interface/response_model.dart';
import 'package:lib/src/request_response/db_request.dart';
import 'package:lib/src/user_details.dart';
import 'package:lib/src/utils/map_helper.dart';
import 'package:lib/src/utils/variables.dart';
class DbApiEndpoint<T extends DbModel> extends ApiEndpoint {
final BaseDatabase<T> database;
class DbApiEndpoint<T extends DbModel, T1 extends ResponseModel> extends ApiEndpoint<T1> {
final BaseDatabase<T, T1> database;
final T Function(Map<String, dynamic>) itemGenerator;
final UserDetails requestingUser;
......@@ -24,9 +25,20 @@ class DbApiEndpoint<T extends DbModel> extends ApiEndpoint {
@override
Future<Map<String, dynamic>> handleGet(context) async {
var id = _idRequestFromContext(context);
var response = await database.get(id);
return context.res.json(response.item.toResponseData());
if(_hasBodyKey(context, RequestResponseVariables.idFieldName)) {
var id = _idRequestFromContext(context);
var response = await database.get(id);
return context.res.json(response.item.toResponseData());
}
else if(_hasBodyKey(context, RequestResponseVariables.queriesFieldName)) {
var queryRequest = _queryRequestFromContext(context);
var response = await database.getFromQueries(queryRequest).toList();
return listResponse(context, response.map((e) => e.item).toList());
}
else {
var response = await database.getAll(DbRequest(item: null, requestingUser: requestingUser)).toList();
return listResponse(context, response.map((e) => e.item).toList());
}
}
@override
......@@ -52,4 +64,15 @@ class DbApiEndpoint<T extends DbModel> extends ApiEndpoint {
var id = getRequiredMapItem<String>(RequestResponseVariables.idFieldName, map);
return DbRequest(item: id, requestingUser: requestingUser);
}
}
\ No newline at end of file
DbRequest<Iterable<String>> _queryRequestFromContext(final context) {
var map = jsonDecode(context.req.body);
var requestedQueries = getRequiredMapItem<Iterable<String>>(RequestResponseVariables.queriesFieldName, map);
return DbRequest(item: requestedQueries, requestingUser: requestingUser);
}
bool _hasBodyKey(final context, String key) {
var map = jsonDecode(context.req.body) as Map<String, dynamic>;
return map.containsKey(key);
}
}
abstract class ApiEndpoint {
import 'dart:convert';
import 'package:lib/src/interface/response_model.dart';
abstract class ApiEndpoint<T extends ResponseModel> {
Future<Map<String, dynamic>> handleGet(final context);
Future<Map<String, dynamic>> handlePost(final context);
Future<Map<String, dynamic>> handlePut(final context);
Future<Map<String, dynamic>> handleDelete(final context);
Map<String, dynamic> listResponse(final context, List<T> response) {
return context.res.send(
jsonEncode(response.map((e) => e.toResponseData()).toList())
);
}
}
......@@ -4,5 +4,4 @@ abstract class DbModel {
String? get id;
Permissions? get permissions;
Map<String, dynamic> toDbData();
Map<String, dynamic> toResponseData();
}