Add support for storage

FossilOrigin-Name: 3c84d235e55a6f4481f3ccfb4007113716902901544f9a1f011723767ecaa1e4
This commit is contained in:
Jonathan Schleifer 2020-10-03 19:47:26 +00:00
parent 491d648e3a
commit 0893233697
12 changed files with 194 additions and 12 deletions

View file

@ -19,3 +19,4 @@ config.status
configure configure
extra.mk extra.mk
tests/tests tests/tests
tests/tests.db

View file

@ -1,4 +1,5 @@
package_format 1 package_format 1
package_depends_on ObjOpenSSL package_depends_on ObjOpenSSL
package_depends_on ObjSQLite3
LIBS="-lobjmatrix $LIBS" LIBS="-lobjmatrix $LIBS"
FRAMEWORK_LIBS="-framework ObjMatrix $FRAMEWORK_LIBS" FRAMEWORK_LIBS="-framework ObjMatrix $FRAMEWORK_LIBS"

View file

@ -9,15 +9,16 @@ It is currently in early development stages.
## How to build it? ## How to build it?
You need [ObjFW](https://objfw.nil.im) and You need [ObjFW](https://objfw.nil.im),
[ObjOpenSSL](https://fossil.nil.im/objopenssl) installed in order to do this. [ObjOpenSSL](https://fossil.nil.im/objopenssl) and
[ObjSQLite3](https://fossil.nil.im/objsqlite3) installed in order to do this.
ObjMatrix uses modern Objective-C, and hence cannot be compiled with GCC, but ObjMatrix uses modern Objective-C, and hence cannot be compiled with GCC, but
only with Clang. So install Clang first and ObjFW will automatically pick it up. only with Clang. So install Clang first and ObjFW will automatically pick it up.
You can install them all like this: You can install them all like this:
$ for i in objfw objopenssl objmatrix; do $ for i in objfw objopenssl objsqlite3 objmatrix; do
fossil clone https://fossil.nil.im/$i $i.fossil && fossil clone https://fossil.nil.im/$i $i.fossil &&
mkdir $i && mkdir $i &&
cd $i && cd $i &&

View file

@ -21,6 +21,11 @@ AS_IF([$OBJFW_CONFIG --package ObjOpenSSL], [
], [ ], [
AC_MSG_ERROR(ObjOpenSSL not found!) AC_MSG_ERROR(ObjOpenSSL not found!)
]) ])
AS_IF([$OBJFW_CONFIG --package ObjSQLite3], [
OBJFW_CONFIG_FLAGS="$OBJFW_CONFIG_FLAGS --package ObjSQLite3"
], [
AC_MSG_ERROR(ObjSQLite3 not found!)
])
test x"$OBJC" = x"" && OBJC="$($OBJFW_CONFIG --objc)" test x"$OBJC" = x"" && OBJC="$($OBJFW_CONFIG --objc)"

View file

@ -22,6 +22,8 @@
#import <ObjFW/ObjFW.h> #import <ObjFW/ObjFW.h>
#import "MTXStorage.h"
OF_ASSUME_NONNULL_BEGIN OF_ASSUME_NONNULL_BEGIN
@class MTXClient; @class MTXClient;
@ -85,39 +87,60 @@ typedef void (^mtx_client_room_join_block_t)(OFString *_Nullable roomID,
*/ */
@property (readonly, nonatomic) OFURL *homeserver; @property (readonly, nonatomic) OFURL *homeserver;
/**
* @brief The storage used by the client.
*/
@property (readonly, nonatomic) id <MTXStorage> storage;
/** /**
* @brief Creates a new client with the specified access token on the specified * @brief Creates a new client with the specified access token on the specified
* homeserver. * homeserver.
* *
* @param userID The user ID for the client
* @param deviceID The device ID for the client
* @param accessToken The access token for the client * @param accessToken The access token for the client
* @param homeserver The URL of the homeserver * @param homeserver The URL of the homeserver
* @param storage The storage the client should use
* @return An autoreleased MTXClient * @return An autoreleased MTXClient
*/ */
+ (instancetype)clientWithUserID: (OFString *)userID + (instancetype)clientWithUserID: (OFString *)userID
deviceID: (OFString *)deviceID deviceID: (OFString *)deviceID
accessToken: (OFString *)accessToken accessToken: (OFString *)accessToken
homeserver: (OFURL *)homeserver; homeserver: (OFURL *)homeserver
storage: (id <MTXStorage>)storage;
/** /**
* @brief Logs into the homeserver and creates a new client. * @brief Logs into the homeserver and creates a new client.
*
* @param user The user to log into
* @param password The password to log in with
* @param homeserver The homeserver to log into
* @param storage The storage the client should use
* @param block A block to call once login succeeded or failed
*/ */
+ (void)logInWithUser: (OFString *)user + (void)logInWithUser: (OFString *)user
password: (OFString *)password password: (OFString *)password
homeserver: (OFURL *)homeserver homeserver: (OFURL *)homeserver
storage: (id <MTXStorage>)storage
block: (mtx_client_login_block_t)block; block: (mtx_client_login_block_t)block;
/** /**
* @brief Initializes an already allocated client with the specified access * @brief Initializes an already allocated client with the specified access
* token on the specified homeserver. * token on the specified homeserver.
* *
* @param userID The user ID for the client
* @param deviceID The device ID for the client
* @param accessToken The access token for the client * @param accessToken The access token for the client
* @param homeserver The URL of the homeserver * @param homeserver The URL of the homeserver
* @param storage The storage the client should use
* @return An initialized MTXClient * @return An initialized MTXClient
*/ */
- (instancetype)initWithUserID: (OFString *)userID - (instancetype)initWithUserID: (OFString *)userID
deviceID: (OFString *)deviceID deviceID: (OFString *)deviceID
accessToken: (OFString *)accessToken accessToken: (OFString *)accessToken
homeserver: (OFURL *)homeserver OF_DESIGNATED_INITIALIZER; homeserver: (OFURL *)homeserver
storage: (id <MTXStorage>)storage
OF_DESIGNATED_INITIALIZER;
/** /**
* @brief Logs out the device and invalidates the access token. * @brief Logs out the device and invalidates the access token.

View file

@ -51,16 +51,19 @@ validateHomeserver(OFURL *homeserver)
deviceID: (OFString *)deviceID deviceID: (OFString *)deviceID
accessToken: (OFString *)accessToken accessToken: (OFString *)accessToken
homeserver: (OFURL *)homeserver homeserver: (OFURL *)homeserver
storage: (id <MTXStorage>)storage
{ {
return [[[self alloc] initWithUserID: userID return [[[self alloc] initWithUserID: userID
deviceID: deviceID deviceID: deviceID
accessToken: accessToken accessToken: accessToken
homeserver: homeserver] autorelease]; homeserver: homeserver
storage: storage] autorelease];
} }
+ (void)logInWithUser: (OFString *)user + (void)logInWithUser: (OFString *)user
password: (OFString *)password password: (OFString *)password
homeserver: (OFURL *)homeserver homeserver: (OFURL *)homeserver
storage: (id <MTXStorage>)storage
block: (mtx_client_login_block_t)block block: (mtx_client_login_block_t)block
{ {
void *pool = objc_autoreleasePoolPush(); void *pool = objc_autoreleasePoolPush();
@ -127,11 +130,11 @@ validateHomeserver(OFURL *homeserver)
} else } else
realHomeserver = homeserver; realHomeserver = homeserver;
MTXClient *client = [MTXClient MTXClient *client = [MTXClient clientWithUserID: userID
clientWithUserID: userID
deviceID: deviceID deviceID: deviceID
accessToken: accessToken accessToken: accessToken
homeserver: realHomeserver]; homeserver: realHomeserver
storage: storage];
block(client, nil); block(client, nil);
}]; }];
@ -142,6 +145,7 @@ validateHomeserver(OFURL *homeserver)
deviceID: (OFString *)deviceID deviceID: (OFString *)deviceID
accessToken: (OFString *)accessToken accessToken: (OFString *)accessToken
homeserver: (OFURL *)homeserver homeserver: (OFURL *)homeserver
storage: (id <MTXStorage>)storage
{ {
self = [super init]; self = [super init];
@ -152,6 +156,7 @@ validateHomeserver(OFURL *homeserver)
_deviceID = [deviceID copy]; _deviceID = [deviceID copy];
_accessToken = [accessToken copy]; _accessToken = [accessToken copy];
_homeserver = [homeserver copy]; _homeserver = [homeserver copy];
_storage = [storage retain];
} @catch (id e) { } @catch (id e) {
[self release]; [self release];
@throw e; @throw e;
@ -166,6 +171,7 @@ validateHomeserver(OFURL *homeserver)
[_deviceID release]; [_deviceID release];
[_accessToken release]; [_accessToken release];
[_homeserver release]; [_homeserver release];
[_storage release];
[super dealloc]; [super dealloc];
} }

48
src/MTXSQLite3Storage.h Normal file
View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2020, Jonathan Schleifer <js@nil.im>
*
* https://fossil.nil.im/objmatrix
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#import "MTXStorage.h"
OF_ASSUME_NONNULL_BEGIN
/**
* @brief SQLite3-based storage for @ref MTXClient.
*/
@interface MTXSQLite3Storage: OFObject <MTXStorage>
/**
* @brief Creates a new SQLite3-based storage for @ref MTXClient.
*
* @param path The path for the SQLite3 database
* @return An autoreleased MTXSQLite3Storage
*/
+ (instancetype)storageWithPath: (OFString *)path;
/**
* @brief Initializes an already allocated MTXSQLite3Storage.
*
* @param path The path for the SQLite3 database
* @return An initialized MTXSQLite3Storage
*/
- (instancetype)initWithPath: (OFString *)path OF_DESIGNATED_INITIALIZER;
@end
OF_ASSUME_NONNULL_END

57
src/MTXSQLite3Storage.m Normal file
View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2020, Jonathan Schleifer <js@nil.im>
*
* https://fossil.nil.im/objmatrix
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#import <ObjSQLite3/ObjSQLite3.h>
#import "MTXSQLite3Storage.h"
@implementation MTXSQLite3Storage
{
SL3Connection *_conn;
}
+ (instancetype)storageWithPath: (OFString *)path
{
return [[[self alloc] initWithPath: path] autorelease];
}
- (instancetype)initWithPath: (OFString *)path
{
self = [super init];
@try {
_conn = [[SL3Connection alloc] initWithPath: path];
} @catch (id e) {
[self release];
@throw e;
}
return self;
}
- (void)dealloc
{
[_conn release];
[super dealloc];
}
@end

33
src/MTXStorage.h Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2020, Jonathan Schleifer <js@nil.im>
*
* https://fossil.nil.im/objmatrix
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#import <ObjFW/ObjFW.h>
OF_ASSUME_NONNULL_BEGIN
/**
* @brief A protocol for a storage to be used by @ref MTXClient.
*/
@protocol MTXStorage <OFObject>
@end
OF_ASSUME_NONNULL_END

View file

@ -9,8 +9,10 @@ LIB_MAJOR = ${OBJMATRIX_LIB_MAJOR}
LIB_MINOR = ${OBJMATRIX_LIB_MINOR} LIB_MINOR = ${OBJMATRIX_LIB_MINOR}
SRCS = MTXClient.m \ SRCS = MTXClient.m \
MTXSQLite3Storage.m \
MTXRequest.m MTXRequest.m
INCLUDES := ${SRCS:.m=.h} \ INCLUDES := ${SRCS:.m=.h} \
MTXStorage.h \
ObjMatrix.h ObjMatrix.h
OBJS_EXTRA = ${EXCEPTIONS_EXCEPTIONS_A} OBJS_EXTRA = ${EXCEPTIONS_EXCEPTIONS_A}

View file

@ -22,6 +22,8 @@
#import "MTXClient.h" #import "MTXClient.h"
#import "MTXRequest.h" #import "MTXRequest.h"
#import "MTXSQLite3Storage.h"
#import "MTXStorage.h"
#import "MTXFetchRoomListFailedException.h" #import "MTXFetchRoomListFailedException.h"
#import "MTXJoinRoomFailedException.h" #import "MTXJoinRoomFailedException.h"

View file

@ -47,9 +47,12 @@ OF_APPLICATION_DELEGATE(Tests)
} }
OFURL *homeserver = [OFURL URLWithString: environment[@"OBJMATRIX_HS"]]; OFURL *homeserver = [OFURL URLWithString: environment[@"OBJMATRIX_HS"]];
id <MTXStorage> storage =
[MTXSQLite3Storage storageWithPath: @"tests.db"];
[MTXClient logInWithUser: environment[@"OBJMATRIX_USER"] [MTXClient logInWithUser: environment[@"OBJMATRIX_USER"]
password: environment[@"OBJMATRIX_PASS"] password: environment[@"OBJMATRIX_PASS"]
homeserver: homeserver homeserver: homeserver
storage: storage
block: ^ (MTXClient *client, id exception) { block: ^ (MTXClient *client, id exception) {
if (exception != nil) { if (exception != nil) {
of_log(@"Error logging in: %@", exception); of_log(@"Error logging in: %@", exception);