blob: 0c98b5fe2dfc6333f21ff8ce1fc5a3ea58218280 [file] [log] [blame]
//
// User.swift
// UsergridSDK
//
// Created by Robert Walsh on 7/21/15.
//
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*
*/
import Foundation
/// The completion block used for checking email and/or username availablity for new `UsergridUser` objects.
public typealias UsergridUserAvailabilityCompletion = (error: UsergridResponseError?, available:Bool) -> Void
/// The completion block used for changing the password of `UsergridUser` objects.
public typealias UsergridUserResetPasswordCompletion = (error: UsergridResponseError?, didSucceed:Bool) -> Void
/**
`UsergridUser` is a special subclass of `UsergridEntity` that supports functions and properties unique to users.
*/
public class UsergridUser : UsergridEntity {
static let USER_ENTITY_TYPE = "user"
// MARK: - Instance Properties -
/// The `UsergridUserAuth` object if this user was authenticated.
public var auth: UsergridUserAuth?
/**
Property helper method for the `UsergridUser` objects `UsergridUserProperties.Name`.
Unlike `UsergridEntity` objects, `UsergridUser`'s can change their name property which is why we provide a getter here.
*/
override public var name: String? {
set(name) { self[UsergridUserProperties.Name.stringValue] = name }
get{ return super.name }
}
/// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Username`.
public var username: String? {
set(username) { self[UsergridUserProperties.Username.stringValue] = username }
get { return self.getUserSpecificProperty(.Username) as? String }
}
/// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Password`.
public var password: String? {
set(password) { self[UsergridUserProperties.Password.stringValue] = password }
get { return self.getUserSpecificProperty(.Password) as? String }
}
/// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Email`.
public var email: String? {
set(email) { self[UsergridUserProperties.Email.stringValue] = email }
get { return self.getUserSpecificProperty(.Email) as? String }
}
/// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Age`.
public var age: NSNumber? {
set(age) { self[UsergridUserProperties.Age.stringValue] = age }
get { return self.getUserSpecificProperty(.Age) as? NSNumber }
}
/// Property helper method to get the username or email of the `UsergridUser`.
public var usernameOrEmail: String? { return self.username ?? self.email }
/**
Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Activated`.
Indicates whether the user account has been activated or not.
*/
public var activated: Bool {
set(activated) { self[UsergridUserProperties.Activated.stringValue] = activated }
get { return self.getUserSpecificProperty(.Activated) as? Bool ?? false }
}
/// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Disabled`.
public var disabled: Bool {
set(disabled) { self[UsergridUserProperties.Disabled.stringValue] = disabled }
get { return self.getUserSpecificProperty(.Disabled) as? Bool ?? false }
}
/**
Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Picture`.
URL path to user’s profile picture. Defaults to Gravatar for email address.
*/
public var picture: String? {
set(picture) { self[UsergridUserProperties.Picture.stringValue] = picture }
get { return self.getUserSpecificProperty(.Picture) as? String }
}
/// The UUID or username property value if found.
public var uuidOrUsername: String? { return self.uuid ?? self.username }
// MARK: - Initialization -
/**
Designated initializer for `UsergridUser` objects.
- parameter name: The name of the user. Note this is different from the `username` property.
- returns: A new instance of `UsergridUser`.
*/
public init(name:String? = nil) {
super.init(type: UsergridUser.USER_ENTITY_TYPE, name:name, propertyDict:nil)
}
/**
The required public initializer for `UsergridEntity` subclasses.
- parameter type: The type associated with the `UsergridEntity` object.
- parameter name: The optional name associated with the `UsergridEntity` object.
- parameter propertyDict: The optional property dictionary that the `UsergridEntity` object will start out with.
- returns: A new `UsergridUser` object.
*/
required public init(type: String, name: String?, propertyDict: [String : AnyObject]?) {
super.init(type: type, name: name, propertyDict: propertyDict)
}
/**
Designated initializer for `UsergridUser` objects.
- parameter name: The name of the user. Note this is different from the `username` property.
- parameter propertyDict: The optional property dictionary that the `UsergridEntity` object will start out with.
- returns: A new instance of `UsergridUser`.
*/
public init(name:String,propertyDict:[String:AnyObject]? = nil) {
super.init(type: UsergridUser.USER_ENTITY_TYPE, name:name, propertyDict:propertyDict)
}
/**
Convenience initializer for `UsergridUser` objects.
- parameter name: The name of the user. Note this is different from the `username` property.
- parameter email: The user's email.
- parameter password: The optional user's password.
- returns: A new instance of `UsergridUser`.
*/
public convenience init(name:String, email:String, password:String? = nil) {
self.init(name:name,email:email,username:nil,password:password)
}
/**
Convenience initializer for `UsergridUser` objects.
- parameter email: The user's email.
- parameter password: The optional user's password.
- returns: A new instance of `UsergridUser`.
*/
public convenience init(email:String, password:String? = nil) {
self.init(name:nil,email:email,username:nil,password:password)
}
/**
Convenience initializer for `UsergridUser` objects.
- parameter name: The name of the user. Note this is different from the `username` property.
- parameter username: The username of the user.
- parameter password: The optional user's password.
- returns: A new instance of `UsergridUser`.
*/
public convenience init(name:String, username:String, password:String? = nil) {
self.init(name:name,email:nil,username:username,password:password)
}
/**
Convenience initializer for `UsergridUser` objects.
- parameter username: The username of the user.
- parameter password: The optional user's password.
- returns: A new instance of `UsergridUser`.
*/
public convenience init(username:String, password:String? = nil) {
self.init(name:nil,email:nil,username:username,password:password)
}
/**
Convenience initializer for `UsergridUser` objects.
- parameter name: The optional name of the user. Note this is different from the `username` property.
- parameter email: The optional user's email.
- parameter username: The optional username of the user.
- parameter password: The optional user's password.
- returns: A new instance of `UsergridUser`.
*/
public convenience init(name:String?, email:String?, username:String?, password:String? = nil) {
self.init(name:name)
self.email = email
self.username = username
self.password = password
}
// MARK: - NSCoding -
/**
NSCoding protocol initializer.
- parameter aDecoder: The decoder.
- returns: A decoded `UsergridUser` object.
*/
required public init?(coder aDecoder: NSCoder) {
self.auth = aDecoder.decodeObjectForKey("auth") as? UsergridUserAuth
super.init(coder: aDecoder)
}
/**
NSCoding protocol encoder.
- parameter aCoder: The encoder.
*/
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(self.auth, forKey: "auth")
super.encodeWithCoder(aCoder)
}
// MARK: - Class Methods -
/**
Checks the given email and/or username availablity for new `UsergridUser` objects using the shared instance of `UsergridClient`.
- parameter email: The optional email address.
- parameter username: The optional username.
- parameter completion: The completion block.
*/
public static func checkAvailable(email:String?, username:String?, completion:UsergridUserAvailabilityCompletion) {
self.checkAvailable(Usergrid.sharedInstance, email: email, username: username, completion: completion)
}
/**
Checks the given email and/or username availablity for new `UsergridUser` objects using with the given `UsergridClient`.
- parameter client: The client to use for checking availability.
- parameter email: The optional email address.
- parameter username: The optional username.
- parameter completion: The completion block.
*/
public static func checkAvailable(client: UsergridClient, email:String?, username:String?, completion:UsergridUserAvailabilityCompletion) {
let query = UsergridQuery(USER_ENTITY_TYPE)
if let emailValue = email {
query.eq(UsergridUserProperties.Email.stringValue, value: emailValue)
}
if let usernameValue = username {
query.or().eq(UsergridUserProperties.Username.stringValue, value: usernameValue)
}
client.GET(query) { (response) -> Void in
completion(error: response.error, available: response.entity == nil)
}
}
// MARK: - Instance Methods -
/**
Creates the user object in Usergrid if the user does not already exist with the shared instance of `UsergridClient`.
- parameter completion: The optional completion block.
*/
public func create(completion: UsergridResponseCompletion? = nil) {
self.create(Usergrid.sharedInstance, completion: completion)
}
/**
Creates the user object in Usergrid if the user does not already exist with the given `UsergridClient`.
- parameter client: The client to use for creation.
- parameter completion: The optional completion block.
*/
public func create(client: UsergridClient, completion: UsergridResponseCompletion? = nil) {
client.POST(self,completion:completion)
}
/**
Authenticates the specified user using the provided username and password with the shared instance of `UsergridClient`.
While functionally similar to `UsergridClient.authenticateUser(auth)`, this method does not automatically assign this user to `UsergridClient.currentUser`:
- parameter username: The username.
- parameter password: The password.
- parameter completion: The optional completion block.
*/
public func login(username:String, password:String, completion: UsergridUserAuthCompletionBlock? = nil) {
self.login(Usergrid.sharedInstance, username: username, password: password, completion: completion)
}
/**
Authenticates the specified user using the provided username and password.
While functionally similar to `UsergridClient.authenticateUser(auth)`, this method does not automatically assign this user to `UsergridClient.currentUser`:
- parameter client: The client to use for login.
- parameter username: The username.
- parameter password: The password.
- parameter completion: The optional completion block.
*/
public func login(client: UsergridClient, username:String, password:String, completion: UsergridUserAuthCompletionBlock? = nil) {
let userAuth = UsergridUserAuth(username: username, password: password)
client.authenticateUser(userAuth,setAsCurrentUser:false) { (auth, user, error) -> Void in
self.auth = userAuth
completion?(auth: userAuth, user: user, error: error)
}
}
/**
Changes the User's current password with the shared instance of `UsergridClient`.
- parameter old: The old password.
- parameter new: The new password.
- parameter completion: The optional completion block.
*/
public func resetPassword(old:String, new:String, completion:UsergridUserResetPasswordCompletion? = nil) {
self.resetPassword(Usergrid.sharedInstance, old: old, new: new, completion: completion)
}
/**
Changes the User's current password with the shared instance of `UsergridClient`.
- parameter client: The client to use for resetting the password.
- parameter old: The old password.
- parameter new: The new password.
- parameter completion: The optional completion block
*/
public func resetPassword(client: UsergridClient, old:String, new:String, completion:UsergridUserResetPasswordCompletion? = nil) {
client.resetPassword(self, old: old, new: new, completion: completion)
}
/**
Attmepts to reauthenticate using the user's `UsergridUserAuth` instance property with the shared instance of `UsergridClient`.
- parameter completion: The optional completion block.
*/
public func reauthenticate(completion: UsergridUserAuthCompletionBlock? = nil) {
self.reauthenticate(Usergrid.sharedInstance, completion: completion)
}
/**
Attmepts to reauthenticate using the user's `UsergridUserAuth` instance property.
- parameter client: The client to use for reauthentication.
- parameter completion: The optional completion block.
*/
public func reauthenticate(client: UsergridClient, completion: UsergridUserAuthCompletionBlock? = nil) {
if let userAuth = self.auth {
client.authenticateUser(userAuth, completion: completion)
} else {
let error = UsergridResponseError(errorName: "Invalid UsergridUserAuth.", errorDescription: "No UsergridUserAuth found on the UsergridUser.")
completion?(auth: nil, user: self, error: error)
}
}
/**
Invalidates the user token locally and remotely.
- parameter completion: The optional completion block.
*/
public func logout(completion:UsergridResponseCompletion? = nil) {
self.logout(Usergrid.sharedInstance,completion:completion)
}
/**
Invalidates the user token locally and remotely.
- parameter client: The client to use for logout.
- parameter completion: The optional completion block.
*/
public func logout(client: UsergridClient, completion:UsergridResponseCompletion? = nil) {
if self === client.currentUser {
client.logoutCurrentUser(completion)
} else if let uuidOrUsername = self.uuidOrUsername, accessToken = self.auth?.accessToken {
client.logoutUser(uuidOrUsername, token: accessToken) { (response) in
self.auth = nil
completion?(response: response)
}
} else {
completion?(response: UsergridResponse(client:client, errorName:"Logout Failed.", errorDescription:"UUID or Access Token not found on UsergridUser object."))
}
}
/**
A special convenience function that connects a `UsergridDevice` to this `UsergridUser` using the shared instance of `UsergridClient`.
- parameter device: The device to connect to. If nil it will use the `UsergridDevice.sharedDevice` instance.
- parameter completion: The optional completion block.
*/
public func connectToDevice(device:UsergridDevice? = nil, completion:UsergridResponseCompletion? = nil) {
self.connectToDevice(Usergrid.sharedInstance, device: device, completion: completion)
}
/**
A special convenience function that connects a `UsergridDevice` to this `UsergridUser`.
- parameter client: The `UsergridClient` object to use for connecting.
- parameter device: The device to connect to. If nil it will use the `UsergridDevice.sharedDevice` instance.
- parameter completion: The optional completion block.
*/
public func connectToDevice(client:UsergridClient, device:UsergridDevice? = nil, completion:UsergridResponseCompletion? = nil) {
let deviceToConnect = device ?? UsergridDevice.sharedDevice
guard let _ = deviceToConnect.uuidOrName
else {
completion?(response: UsergridResponse(client: client, errorName: "Device cannot be connected to User.", errorDescription: "Device has neither an UUID or name specified."))
return
}
self.connect(client, relationship: "devices", toEntity: deviceToConnect, completion: completion)
}
/**
A special convenience function that disconnects a `UsergridDevice` from this `UsergridUser` using the shared instance of `UsergridClient`.
- parameter device: The device to connect to. If nil it will use the `UsergridDevice.sharedDevice` instance.
- parameter completion: The optional completion block.
*/
public func disconnectFromDevice(device:UsergridDevice? = nil, completion:UsergridResponseCompletion? = nil) {
self.disconnectFromDevice(Usergrid.sharedInstance, device: device, completion: completion)
}
/**
A special convenience function that disconnects a `UsergridDevice` from this `UsergridUser`.
- parameter client: The `UsergridClient` object to use for connecting.
- parameter device: The device to connect to.
- parameter completion: The optional completion block.
*/
public func disconnectFromDevice(client:UsergridClient, device:UsergridDevice? = nil, completion:UsergridResponseCompletion? = nil) {
let deviceToDisconnectFrom = device ?? UsergridDevice.sharedDevice
guard let _ = deviceToDisconnectFrom.uuidOrName
else {
completion?(response: UsergridResponse(client: client, errorName: "Device cannot be disconnected from User.", errorDescription: "Device has neither an UUID or name specified."))
return
}
self.disconnect(client, relationship: "devices", fromEntity: deviceToDisconnectFrom, completion: completion)
}
private func getUserSpecificProperty(userProperty: UsergridUserProperties) -> AnyObject? {
var propertyValue: AnyObject? = super[userProperty.stringValue]
NSJSONReadingOptions.AllowFragments
switch userProperty {
case .Activated,.Disabled :
propertyValue = propertyValue?.boolValue
case .Age :
propertyValue = propertyValue?.integerValue
case .Name,.Username,.Password,.Email,.Picture :
break
}
return propertyValue
}
/**
Subscript for the `UsergridUser` class.
- Warning: When setting a properties value must be a valid JSON object.
- Example usage:
```
let someName = usergridUser["name"]
usergridUser["name"] = someName
```
*/
override public subscript(propertyName: String) -> AnyObject? {
get {
if let userProperty = UsergridUserProperties.fromString(propertyName) {
return self.getUserSpecificProperty(userProperty)
} else {
return super[propertyName]
}
}
set(propertyValue) {
super[propertyName] = propertyValue
}
}
}