Skip to content

Instantly share code, notes, and snippets.

@jadechip
Created May 13, 2015 14:05
Show Gist options
  • Save jadechip/9ab60146405c65fb54a4 to your computer and use it in GitHub Desktop.
Save jadechip/9ab60146405c65fb54a4 to your computer and use it in GitHub Desktop.
Objective-C classes for retrieving a user authentication token and storing it in the keychain using AFNetworking and SSKeychain
//
// APIHandler.h
// Orakuru
//
// Created by Mitrmitri on 11/19/2557 BE.
// Copyright (c) 2557 Codemy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AFNetworking/AFNetworking.h>
@class Listing;
@class Tag;
@class User;
@class Connection;
@class ContactPerson;
@class Address;
@interface APIHandler : NSObject
+ (AFHTTPRequestOperationManager *)configureHeaderForAuthenticatedRequestUser:(User *)user;
+ (void)updateListing:(Listing *)listing
byUser:(User *)currentUser
success:(void (^)())success
failure:(void(^)(NSString *error))failure;
#pragma mark - Search Listings
+ (void)searchListingWithQuery:(NSString *)searchText
latitude:(double)lat
longitude:(double)lon
categoryIDs:(NSArray *)categoryIDs
regionIDs:(NSArray *)regionIDs
tagIDs:(NSArray *)tagIDs
paging:(NSInteger)pageNunber
success:(void(^)(NSArray *listings))success
failure:(void(^)(NSString *message))failure;
+ (void)searchListingWithQuery:(NSString *)searchText
paging:(NSInteger)pageNunber
success:(void(^)(NSArray *listings))success
failure:(void(^)(NSString *message))failure;
+ (void)loginInWithEmail:(NSString *)email
AndPassword:(NSString *)password
AndUUID:(NSString *)UUID
success:(void(^)(User *user))success
failure:(void(^)(NSError *error))failure;
#pragma mark - Get Listing Detail
+ (void)getListingWithID:(NSInteger)ID
success:(void(^)(Listing *listing))success
failure:(void(^)(NSString *message))failure;
+ (void)searchRegionsWithParameters:(NSString *)keyword
success:(void(^)(NSArray *regions))success
failure:(void(^)(NSString *error))failure;
#pragma mark - Tags Keywords
+ (void)searchTagsWithKeyword:(NSString *)keyword
success:(void(^)(NSArray *keywords))success
failure:(void(^)(NSString *error))failure;
+ (void)createTag:(Tag *)tag
user:(User *)currentUser
success:(void(^)(Tag *tag))success
failure:(void(^)(NSString *error))failure;
#pragma mark - connections
+ (void)createConnection:(Connection *)connection
success:(void(^)(NSNumber *Id))success
failure:(void(^)(NSError *error))failure;
+ (void)deleteConnectionId:(NSNumber *)Id
success:(void(^)())success
failure:(void(^)(NSError *error))failure;
#pragma mark - addresses
+ (void)createAddress:(Address *)address
success:(void(^)(NSNumber *Id))success
failure:(void(^)(NSError *))failure;
+ (void)deleteAddressId:(NSNumber *)Id
success:(void(^)())success
failure:(void(^)(NSError *))failure;
#pragma mark - photos
+ (void)createPhoto:(NSURL *)photoURL
forListing:(Listing *)listing
success:(void(^)(NSNumber *photoID))success
failure:(void(^)(NSError *error))failure;
+ (void)getUniquePhotoKeySuccess:(void(^)(NSString *key))success
failure:(void(^)(NSError *error))failure;
+ (void)deletePhoto:(NSNumber *)photoID
success:(void(^)())success
failure:(void(^)(NSError *error))failure;
+ (void)searchListingsWithUser:(User *)currentUser
success:(void (^)(NSArray *listings))success
failure:(void (^)(NSString *error))failure;
#pragma mark - contact people
+ (void)createContactPerson:(ContactPerson *)contactPerson
success:(void(^)(NSNumber *Id))success
failure:(void(^)(NSError *))failure;
+ (void)deleteContactPsersonId:(NSNumber *)Id
success:(void(^)())success
failure:(void(^)(NSError *))failure;
@end
//
// APIHandler.m
// Orakuru
//
// Created by Mitrmitri on 11/19/2557 BE.
// Copyright (c) 2557 Codemy. All rights reserved.
//
#import "APIHandler.h"
#import "Listing.h"
#import "Region.h"
#import "User.h"
#import "Tag.h"
#import "Address.h"
#import "TokenStorage.h"
#import "User.h"
#import "ContactPerson.h"
#import "Connection.h"
#import <CoreLocation/CoreLocation.h>
#import <Mantle/MTLJSONAdapter.h>
@interface AFHTTPRequestOperationManager(Auth)
+ (instancetype)authManager:(User *)user;
@end
@implementation AFHTTPRequestOperationManager (Auth)
+ (instancetype)authManager:(User *)user {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:[user.userID stringValue]
forHTTPHeaderField:@"X-User-Id"];
[manager.requestSerializer setValue:user.UUID
forHTTPHeaderField:@"X-Device-Uid"];
[manager.requestSerializer setValue:user.authToken
forHTTPHeaderField:@"X-Auth-Token"];
return manager;
}
@end
@implementation APIHandler
+ (void)searchListingWithQuery:(NSString *)searchText
paging:(NSInteger)pageNunber
success:(void(^)(NSArray *listings))success
failure:(void(^)(NSString *message))failure
{
// In the case of an empty search query
if ([searchText isEqualToString:@""]) {
searchText = @"Sushi";
}
NSDictionary * parameters = @{@"q" : searchText,
@"page" : @(pageNunber)};
[self searchListingWithParams:parameters
success:success
failure:failure];
}
+ (void)searchListingWithQuery:(NSString *)searchText
latitude:(double)lat
longitude:(double)lon
categoryIDs:(NSArray *)categoryIDs
regionIDs:(NSArray *)regionIDs
tagIDs:(NSArray *)tagIDs
paging:(NSInteger)pageNunber
success:(void(^)(NSArray *listings))success
failure:(void(^)(NSString *message))failure
{
// In the case of an empty search query
if (!searchText || [searchText isEqualToString:@""]) {
@throw [NSException exceptionWithName:NSInvalidArgumentException
reason:@"SearchText must not be nil or empty string"
userInfo:nil];
}
NSMutableDictionary * parameters = [@{@"q" : searchText,
@"lat" : @(lat),
@"lon" : @(lon),
@"page" : @(pageNunber)} mutableCopy];
if (regionIDs.count > 0) parameters[@"r"] = regionIDs;
if (categoryIDs.count > 0) parameters[@"c"] = categoryIDs;
if (tagIDs.count > 0 ) parameters[@"k"] = tagIDs;
[self searchListingWithParams:parameters
success:success
failure:failure];
}
+ (void)searchListingWithParams:(NSDictionary *)params
success:(void(^)(NSArray *listings))success
failure:(void(^)(NSString *message))failure {
// Query encoding
NSString * url = [BASE_URL stringByAppendingPathComponent:@"v1/search"];
[[AFHTTPRequestOperationManager manager] GET:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSArray * listings = [MTLJSONAdapter modelsOfClass:[Listing class]
fromJSONArray:responseObject[@"listings"]
error:nil];
success(listings);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",error);
}];
}
+ (void)getListingWithID:(NSInteger)ID
success:(void (^)(Listing *))success
failure:(void (^)(NSString *))failure {
NSString *resourcePath = [NSString stringWithFormat:@"v1/listings/%ld", (long)ID];
NSString *url = [BASE_URL stringByAppendingPathComponent:resourcePath];
[[AFHTTPRequestOperationManager manager] GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
Listing *listing = [MTLJSONAdapter modelOfClass:[Listing class]
fromJSONDictionary:responseObject
error:nil];
listing.fetched = YES;
success(listing);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error.description);
}];
}
#pragma mark - My Listings
+ (void)searchListingsWithUser:(User *)currentUser
success:(void (^)(NSArray *listings))success
failure:(void (^)(NSString *error))failure {
NSString *url = [NSString stringWithFormat:@"%@/v1/listings",BASE_URL];
AFHTTPRequestOperationManager *manager = [self configureHeaderForAuthenticatedRequestUser:currentUser];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSArray *listings = [MTLJSONAdapter modelsOfClass:[Listing class] fromJSONArray:responseObject error:nil];
success(listings);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure([error description]);
}];
}
#pragma mark - Region Handler
+ (void)searchRegionsWithParameters:(NSString *)keyword
success:(void(^)(NSArray *regions))success
failure:(void(^)(NSString *error))failure {
// TODO: Change BASE_URL to comply with updated conventions
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/regions"];
NSDictionary *parameters = @{@"q":keyword};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSArray * regions = [MTLJSONAdapter modelsOfClass:[Region class] fromJSONArray:responseObject error:nil];
success(regions);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@", error);
}];
}
#pragma mark - Tag API
+ (void)searchTagsWithKeyword:(NSString *)keyword
success:(void (^)(NSArray *))success
failure:(void (^)(NSString *))failure {
// TO DO: Change BASE_URL to comply with updated conventions
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/tags"];
NSDictionary *parameters = @{@"name":keyword};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSArray * tags = [MTLJSONAdapter modelsOfClass:[Tag class]
fromJSONArray:responseObject
error:nil];
success(tags);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure([error description]);
}];
}
+ (void)createTag:(Tag *)tag
user:(User *)currentUser
success:(void (^)(Tag *))success
failure:(void (^)(NSString *))failure {
// TO DO: Change BASE_URL to comply with updated conventions
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/tags"];
NSDictionary *parameters = [MTLJSONAdapter JSONDictionaryFromModel:tag];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:url
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
Tag *response = [MTLJSONAdapter modelOfClass:[Tag class]
fromJSONDictionary:responseObject
error:nil];
tag.ID = response.ID;
success(tag);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure([error description]);
}];
}
+ (id)JSONWithFile:(NSString *)fileName {
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName
ofType:@"json"];
NSData *JSONData = [NSData dataWithContentsOfFile:filePath];
return [NSJSONSerialization JSONObjectWithData:JSONData
options:kNilOptions
error:nil];
}
#pragma mark - connections
+ (void)createConnection:(Connection *)connection
success:(void(^)(NSNumber *Id))success
failure:(void(^)(NSError *error))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/connections"];
NSDictionary *connectionDict = [MTLJSONAdapter JSONDictionaryFromModel:connection];
NSDictionary *params = @{@"connection": connectionDict};
[manager POST:url
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
success(responseObject[@"id"]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
+ (void)deleteConnectionId:(NSNumber *)Id
success:(void(^)())success
failure:(void(^)(NSError *error))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
NSString *resourcePath = [NSString stringWithFormat:@"v1/connections/%@", [Id stringValue]];
NSString *url = [BASE_URL stringByAppendingPathComponent:resourcePath];
[manager DELETE:url
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
success();
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
#pragma mark - User Handler
+ (void)loginInWithEmail:(NSString *)email
AndPassword:(NSString *)password
AndUUID:(NSString *)UUID
success:(void(^)(User *user))success
failure:(void(^)(NSError *error))failure {
NSDictionary *userDict = @{@"email":email, @"password":password};
NSDictionary *deviceDict = @{@"uid":UUID};
NSDictionary *params = @{@"user":userDict, @"device":deviceDict};
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/sessions"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:url
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *userID = [responseObject objectForKey:@"user_id"];
NSNumber *userIDNumber = @([userID intValue]);
// User becomes initialized
User *user = [[User alloc] initWithEmail:email
AndPassword:password
AndUUID:UUID
AndUserID:userIDNumber
AndAuthToken:[responseObject objectForKey:@"authentication_token"]];
// Return User
success(user);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
+ (AFHTTPRequestOperationManager *)configureHeaderForAuthenticatedRequestUser:(User *)currentUser {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:[currentUser.userID stringValue]
forHTTPHeaderField:@"X-User-Id"];
[manager.requestSerializer setValue:currentUser.UUID
forHTTPHeaderField:@"X-Device-Uid"];
[manager.requestSerializer setValue:currentUser.authToken
forHTTPHeaderField:@"X-Auth-Token"];
return manager;
}
#pragma mark - update Listing
+ (void)updateListing:(Listing *)listing
byUser:(User *)currentUser
success:(void (^)())success
failure:(void(^)(NSString *error))failure {
NSString *url = [NSString stringWithFormat:@"%@/v1/listings/%@",BASE_URL,listing.ID];
NSDictionary *parameters = @{ @"listing" :
@{
@"name" : [self checkStringIsNull:listing.name],
@"market_name" : [self checkStringIsNull:listing.marketName],
@"short_description" : [self checkStringIsNull:listing.shortDescription],
@"long_description" : [self checkStringIsNull:listing.longDescription],
@"tag_tokens" : [listing tagAsCSV],
@"main_email" : [self checkStringIsNull:listing.mainEmail],
@"main_phone" : [self checkStringIsNull:listing.mainPhone],
@"main_fax" : [self checkStringIsNull:listing.mainFax],
@"facebook" : [self checkStringIsNull:listing.facebook],
@"twitter" : [self checkStringIsNull:listing.twitter],
@"instagram" : [self checkStringIsNull:listing.instagram],
@"google_plus" : [self checkStringIsNull:listing.googlePlus],
@"latitude" : [NSNumber numberWithDouble:listing.coordinates.latitude],
@"longitude" : [NSNumber numberWithDouble:listing.coordinates.longitude],
@"connection_ids" : [listing allConnectionIds],
@"person_ids" : [listing personIds],
@"address_ids" : [listing allAddressIds]
}
};
AFHTTPRequestOperationManager *manager = [self configureHeaderForAuthenticatedRequestUser:currentUser];
[manager PUT:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
success();
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error.description);
}];
}
+ (NSString *)checkStringIsNull:(NSString *)value {
if (!value) {
return (NSString *)[NSNull null];
}
return value;
}
#pragma mark - addresses
+ (void)createAddress:(Address *)address
success:(void (^)(NSNumber *))success
failure:(void (^)(NSError *))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/addresses"];
NSDictionary *params = @{@"address": [MTLJSONAdapter JSONDictionaryFromModel:address]};
[manager POST:url
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
success(responseObject[@"id"]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
+ (void)deleteAddressId:(NSNumber *)Id
success:(void (^)())success
failure:(void (^)(NSError *))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
NSString *resourcePath = [NSString stringWithFormat:@"v1/addresses/%@", [Id stringValue]];
NSString *url = [BASE_URL stringByAppendingPathComponent:resourcePath];
[manager DELETE:url
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
success();
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
#pragma mark - photos
+ (void)createPhoto:(NSURL *)photoURL
forListing:(Listing *)listing
success:(void(^)(NSNumber *photoID))success
failure:(void(^)(NSError *error))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
NSInteger uploadsIndex = [[photoURL absoluteString] rangeOfString:@"uploads/"].location;
NSString *photoKey = [[photoURL absoluteString] substringFromIndex:uploadsIndex];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"photo"] = @{@"key":photoKey};
params[@"listing_id"] = [listing.ID stringValue];
[manager POST:[BASE_URL stringByAppendingPathComponent:@"v1/photos"]
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSNumber *photoID = responseObject[@"id"];
success(photoID);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
+ (void)getUniquePhotoKeySuccess:(void (^)(NSString *))success
failure:(void (^)(NSError *))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
[manager GET:[BASE_URL stringByAppendingPathComponent:@"v1/photos/new"]
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *key = responseObject[@"key"];
if (key.length > 0) {
success(key);
} else {
failure([NSError errorWithDomain:@"API"
code:0
userInfo:@{NSLocalizedDescriptionKey: @"Cannot request key for photo creation"}]);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
+ (void)deletePhoto:(NSNumber *)photoID
success:(void(^)())success
failure:(void(^)(NSError *error))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/photos"];
url = [url stringByAppendingPathComponent:[photoID stringValue]];
[manager DELETE:url
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
success();
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
#pragma mark - contact people
+ (void)createContactPerson:(ContactPerson *)contactPerson
success:(void(^)(NSNumber *Id))success
failure:(void(^)(NSError *))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/people"];
NSDictionary *params = @{@"person":[MTLJSONAdapter JSONDictionaryFromModel:contactPerson]};
[manager POST:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
success(responseObject[@"id"]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
+ (void)deleteContactPsersonId:(NSNumber *)Id
success:(void(^)())success
failure:(void(^)(NSError *))failure {
User *user = [User currentUser];
if (!user || !user.isLogin) {
NSString *msg = [NSString stringWithFormat:@"%s need authentication", __func__];
failure([NSError errorWithDomain:@"Authentication"
code:0
userInfo:@{NSLocalizedDescriptionKey:msg}]);
return;
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager authManager:user];
NSString *url = [BASE_URL stringByAppendingPathComponent:@"v1/people"];
url = [url stringByAppendingPathComponent:[Id stringValue]];
[manager DELETE:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
success();
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
@end
//
// TokenStorage.h
// Orakuru
//
// Created by Developer on 12/03/2015.
// Copyright (c) 2015 Codemy. All rights reserved.
//
// Saving the Token in the device (keychain)
#import <Foundation/Foundation.h>
#import <SSKeychain.h>
#import "User.h"
// Service Name
static NSString * const kServiceName = @"Orakuru";
// Keys
static NSString * const kAuthToken = @"authentication_token";
static NSString * const kEmail = @"email";
static NSString * const kUserID = @"userID";
static NSString * const kUUID = @"UUID";
static NSString * const kIsLogin = @"isLogin";
@interface TokenStorage : NSObject
- (void)clearSavedCredentialsOfUser:(User *)credentials;
- (NSString *)getSecureStringValueForKey:(id)key;
- (void)saveUserCredentials:(User *)credentials;
@end
//
// TokenStorage.m
// Orakuru
//
// Created by Developer on 12/03/2015.
// Copyright (c) 2015 Codemy. All rights reserved.
//
#import "TokenStorage.h"
#define SERVICE_NAME @"Orakuru"
#define AUTH_TOKEN_KEY @"authentication_token"
@implementation TokenStorage
- (NSDictionary *)createDictionaryFromUserCredentials:(User *)credentials {
NSString *userIDString = [credentials.userID stringValue];
NSString *userIsLoginString = credentials.isLogin ? @"YES" : @"NO";
return @{
kEmail:credentials.email,
kUserID:userIDString,
kUUID:credentials.UUID,
kAuthToken:credentials.authToken,
kIsLogin:userIsLoginString
};
}
- (void)saveUserCredentials:(User *)credentials {
NSDictionary *container = [self createDictionaryFromUserCredentials:credentials];
for(id key in container.allKeys) {
id value = [container objectForKey:key];
[SSKeychain setPassword:value
forService:SERVICE_NAME
account:key];
}
}
#pragma mark - Get secure value
- (NSString *)getSecureStringValueForKey:(NSString *)key {
return [SSKeychain passwordForService:SERVICE_NAME account:key];
}
#pragma mark - Clear credentials
- (void)clearSavedCredentialsOfUser:(User *)credentials {
NSDictionary *container = [self createDictionaryFromUserCredentials:credentials];
for (id key in container.allKeys) {
[SSKeychain deletePasswordForService:SERVICE_NAME account:key];
}
}
@end
//
// User.h
// Orakuru
//
// Created by offz on 2/25/2558 BE.
// Copyright (c) 2558 Codemy. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface User : NSObject
@property (assign, nonatomic, readonly) BOOL isLogin;
@property (strong, nonatomic) NSString *UUID;
@property (strong, nonatomic) NSNumber *userID;
@property (strong, nonatomic) NSString *email;
@property (strong, nonatomic) NSString *password;
@property (strong, nonatomic) NSString *authToken;
+ (instancetype)currentUser;
- (instancetype)initWithEmail:(NSString *)email
AndPassword:(NSString *)password
AndUUID:(NSString *)UUID
AndUserID:(NSNumber *)userID
AndAuthToken:(NSString *)authToken;
- (void)logOut:(User *)currentUser;
- (void)assignValueToCurrentUser;
@end
//
// User.m
// Orakuru
//
// Created by offz on 2/25/2558 BE.
// Copyright (c) 2558 Codemy. All rights reserved.
//
#import "User.h"
#import <AFNetworking/AFNetworking.h>
#import "TokenStorage.h"
@interface User()
@property (strong, nonatomic) TokenStorage *store;
// Not writeable from public API
@property (assign, nonatomic, readwrite) BOOL isLogin;
@end
@implementation User
// Designated initializer
- (instancetype)initWithEmail:(NSString *)email
AndPassword:(NSString *)password
AndUUID:(NSString *)UUID
AndUserID:(NSNumber *)userID
AndAuthToken:(NSString *)authToken {
self = [super init];
if (self) {
_email = email;
_password = password;
_UUID = UUID;
_userID = userID;
_authToken = authToken;
if (!_store) {
_store = [[TokenStorage alloc] init];
}
[_store saveUserCredentials:self];
[self assignValueToCurrentUser];
}
return self;
}
- (void)logOut:(User *)currentUser {
[self.store clearSavedCredentialsOfUser:currentUser];
[self resetCurrentUser];
}
+ (instancetype)currentUser {
static User *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [User new];
instance.isLogin = NO;
});
return instance;
}
- (void)assignValueToCurrentUser {
[User currentUser].isLogin = [self.store getSecureStringValueForKey:kIsLogin];
if ([User currentUser].isLogin) {
[User currentUser].email = [self.store getSecureStringValueForKey:kEmail];
[User currentUser].UUID = [self.store getSecureStringValueForKey:kUUID];
[User currentUser].userID = @([[self.store getSecureStringValueForKey:kUserID] intValue]);
[User currentUser].authToken = [self.store getSecureStringValueForKey:kAuthToken];
}
}
- (void)resetCurrentUser {
[User currentUser].isLogin = NO;
[User currentUser].email = nil;
[User currentUser].UUID = nil;
[User currentUser].userID = nil;
[User currentUser].authToken = nil;
}
-(TokenStorage *)store {
if (!_store) {
_store = [[TokenStorage alloc] init];
}
return _store;
}
- (NSString *)email {
if (self.isLogin) {
_email = [self.store getSecureStringValueForKey:kEmail];
}
return _email;
}
- (NSNumber *)userID {
if (self.isLogin) {
NSNumber *userID = @([[self.store getSecureStringValueForKey:kUserID] intValue]);
_userID = userID;
}
return _userID;
}
- (NSString *)UUID {
if (self.isLogin) {
_UUID = [self.store getSecureStringValueForKey:kUUID];
}
return _UUID;
}
- (NSString *)authToken {
if (self.isLogin) {
_authToken = [self.store getSecureStringValueForKey:kAuthToken];
}
return _authToken;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment