Add MTXRequest, MTXClient & support for logging in
FossilOrigin-Name: 1e716c7f85cbebd8a6cdddaee2605897beeb69d0a20150ab5a300254007648e4
This commit is contained in:
parent
6adffeb699
commit
d2bb4edae9
13 changed files with 794 additions and 0 deletions
173
src/MTXClient.m
Normal file
173
src/MTXClient.m
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* 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 "MTXClient.h"
|
||||
#import "MTXRequest.h"
|
||||
|
||||
#import "MTXLoginFailedException.h"
|
||||
|
||||
static void
|
||||
validateHomeserver(OFURL *homeserver)
|
||||
{
|
||||
if (![homeserver.scheme isEqual: @"http"] &&
|
||||
![homeserver.scheme isEqual: @"https"])
|
||||
@throw [OFUnsupportedProtocolException
|
||||
exceptionWithURL: homeserver];
|
||||
|
||||
if (homeserver.path != nil && ![homeserver.path isEqual: @"/"])
|
||||
@throw [OFInvalidArgumentException exception];
|
||||
|
||||
if (homeserver.user != nil || homeserver.password != nil ||
|
||||
homeserver.query != nil || homeserver.fragment != nil)
|
||||
@throw [OFInvalidArgumentException exception];
|
||||
}
|
||||
|
||||
@implementation MTXClient
|
||||
+ (instancetype)clientWithUserID: (OFString *)userID
|
||||
deviceID: (OFString *)deviceID
|
||||
accessToken: (OFString *)accessToken
|
||||
homeserver: (OFURL *)homeserver
|
||||
{
|
||||
return [[[self alloc] initWithUserID: userID
|
||||
deviceID: deviceID
|
||||
accessToken: accessToken
|
||||
homeserver: homeserver] autorelease];
|
||||
}
|
||||
|
||||
+ (void)logInWithUser: (OFString *)user
|
||||
password: (OFString *)password
|
||||
homeserver: (OFURL *)homeserver
|
||||
block: (mtx_client_login_block_t)block
|
||||
{
|
||||
void *pool = objc_autoreleasePoolPush();
|
||||
|
||||
validateHomeserver(homeserver);
|
||||
|
||||
MTXRequest *request = [MTXRequest
|
||||
requestWithPath: @"/_matrix/client/r0/login"
|
||||
accessToken: nil
|
||||
homeserver: homeserver];
|
||||
request.method = OF_HTTP_REQUEST_METHOD_POST;
|
||||
request.body = @{
|
||||
@"type": @"m.login.password",
|
||||
@"identifier": @{
|
||||
@"type": @"m.id.user",
|
||||
@"user": user
|
||||
},
|
||||
@"password": password
|
||||
};
|
||||
|
||||
[request asyncPerformWithBlock:
|
||||
^ (OFDictionary<OFString *, id> *response, int statusCode,
|
||||
id exception) {
|
||||
if (exception != nil) {
|
||||
block(nil, exception);
|
||||
return;
|
||||
}
|
||||
|
||||
if (statusCode != 200) {
|
||||
id exception = [MTXLoginFailedException
|
||||
exceptionWithUser: user
|
||||
homeserver: homeserver
|
||||
statusCode: statusCode
|
||||
response: response];
|
||||
block(nil, exception);
|
||||
return;
|
||||
}
|
||||
|
||||
OFString *userID = response[@"user_id"];
|
||||
OFString *deviceID = response[@"device_id"];
|
||||
OFString *accessToken = response[@"access_token"];
|
||||
if (userID == nil || deviceID == nil ||
|
||||
accessToken == nil) {
|
||||
block(nil, [OFInvalidServerReplyException exception]);
|
||||
return;
|
||||
}
|
||||
|
||||
OFString *baseURL =
|
||||
response[@"well_known"][@"m.homeserver"][@"base_url"];
|
||||
OFURL *realHomeserver;
|
||||
if (baseURL != nil) {
|
||||
@try {
|
||||
realHomeserver = [OFURL URLWithString: baseURL];
|
||||
} @catch (id e) {
|
||||
block(nil, e);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
realHomeserver = homeserver;
|
||||
|
||||
MTXClient *client = [MTXClient
|
||||
clientWithUserID: userID
|
||||
deviceID: deviceID
|
||||
accessToken: accessToken
|
||||
homeserver: realHomeserver];
|
||||
block(client, nil);
|
||||
}];
|
||||
|
||||
objc_autoreleasePoolPop(pool);
|
||||
}
|
||||
|
||||
- (instancetype)initWithUserID: (OFString *)userID
|
||||
deviceID: (OFString *)deviceID
|
||||
accessToken: (OFString *)accessToken
|
||||
homeserver: (OFURL *)homeserver
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
@try {
|
||||
validateHomeserver(homeserver);
|
||||
|
||||
_userID = [userID copy];
|
||||
_deviceID = [deviceID copy];
|
||||
_accessToken = [accessToken copy];
|
||||
_homeserver = [homeserver copy];
|
||||
} @catch (id e) {
|
||||
[self release];
|
||||
@throw e;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_userID release];
|
||||
[_deviceID release];
|
||||
[_accessToken release];
|
||||
[_homeserver release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (OFString *)description
|
||||
{
|
||||
return [OFString stringWithFormat:
|
||||
@"<%@\n"
|
||||
@"\tUser ID = %@\n"
|
||||
@"\tDevice ID = %@\n"
|
||||
@"\tAccess token = %@\n"
|
||||
@"\tHomeserver = %@\n"
|
||||
@">",
|
||||
self.class, _userID, _deviceID, _accessToken, _homeserver];
|
||||
}
|
||||
@end
|
Loading…
Add table
Add a link
Reference in a new issue