Skip to content
This repository was archived by the owner on Mar 9, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Couch/CouchCocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
#import "CouchDesignDocument.h"
#import "CouchDocument.h"
#import "CouchModel.h"
#import "CouchUser.h"
#import "CouchSecurity.h"
#import "CouchPersistentReplication.h"
#import "CouchQuery.h"
#import "CouchRevision.h"
#import "CouchServer.h"
#import "CouchTouchDBServer.h"

#import "CouchTouchDBDatabase.h"

/** @mainpage About CouchCocoa

Expand Down
6 changes: 5 additions & 1 deletion Couch/CouchDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#import "CouchResource.h"
#import "CouchReplication.h"
@class RESTCache, CouchChangeTracker, CouchDocument, CouchDesignDocument, CouchModelFactory,
CouchPersistentReplication, CouchQuery, CouchServer;
CouchPersistentReplication, CouchQuery, CouchServer, CouchSecurity;

typedef NSString* (^CouchDocumentPathMap)(NSString* documentID);

Expand Down Expand Up @@ -166,6 +166,10 @@ typedef NSString* (^CouchDocumentPathMap)(NSString* documentID);
/** All currently configured persistent replications involving this database, as CouchPersistentReplication objects. */
@property (readonly) NSArray* replications;

#pragma mark SECURITY OBJECT:

- (CouchSecurity*)security;

@end


Expand Down
6 changes: 6 additions & 0 deletions Couch/CouchDatabase.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#import "CouchDatabase.h"
#import "RESTCache.h"
#import "CouchChangeTracker.h"
#import "CouchSecurity.h"
#import "CouchInternal.h"


Expand Down Expand Up @@ -357,7 +358,12 @@ - (NSArray*) replicateWithURL: (NSURL*)targetURL exclusively: (BOOL)exclusively
return repls;
}

#pragma mark -
#pragma mark SECURITY OBJECT:

- (CouchSecurity*)security {
return [[[CouchSecurity alloc] initWithDatabase:self] autorelease];
}

#pragma mark -
#pragma mark TRACKING CHANGES:
Expand Down
12 changes: 11 additions & 1 deletion Couch/CouchDocument.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ - (NSString*) description {
@synthesize isDeleted=_isDeleted, modelObject=_modelObject;


- (void) resetCurrentRevision {
[_currentRevisionID autorelease];
_currentRevisionID = nil;
[_currentRevision autorelease];
_currentRevision = nil;
}


- (NSString*) currentRevisionID {
return _currentRevisionID;
}
Expand Down Expand Up @@ -416,8 +424,10 @@ - (void) bulkSaveCompleted: (NSDictionary*) result forProperties: (NSDictionary*
if (![properties objectForKey: @"_id"]) {
NSMutableDictionary* nuProperties = [[properties mutableCopy] autorelease];
[nuProperties setObject: docID forKey: @"_id"];
NSString* rev = [result objectForKey:@"rev"];
if (rev) [nuProperties setObject:rev forKey: @"_rev"];
properties = nuProperties;
}
}
[self updateFromSaveResponse: result withProperties: properties];
}
}
Expand Down
13 changes: 13 additions & 0 deletions Couch/CouchInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ typedef void (^OnDatabaseChangeBlock)(CouchDocument*, BOOL externalChange);
- (void) loadCurrentRevisionFrom: (CouchQueryRow*)row;
- (void) bulkSaveCompleted: (NSDictionary*) result forProperties: (NSDictionary*)properties;
- (BOOL) notifyChanged: (NSDictionary*)change;
- (void) resetCurrentRevision;
@end


Expand Down Expand Up @@ -82,13 +83,25 @@ typedef void (^OnDatabaseChangeBlock)(CouchDocument*, BOOL externalChange);
@property (readonly) NSString* targetURLStr;
@end

@interface CouchDynamicObject ()
- (void) updateProperties:(NSDictionary*)properties strict:(BOOL)strict;
@end

@interface CouchModel ()
- (BOOL) isEmbeddedModelProperty: (NSString*)property;
@end

@interface CouchSecurity ()
- (id) initWithDatabase: (CouchDatabase*)database;
@end


@interface CouchServer ()
@property (readonly) BOOL isEmbeddedServer;
- (CouchPersistentReplication*) replicationWithSource: (NSString*)source
target: (NSString*)target;
- (void) registerActiveTask: (NSDictionary*)activeTask;
- (Class) userModelClass;
@end


Expand Down
3 changes: 3 additions & 0 deletions Couch/CouchResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ extern NSString* const kCouchDBErrorDomain;
/** The owning database. */
@property (readonly) CouchDatabase* database;

/** Performs a HEAD request to check if the resource exists. */
- (BOOL) exists;

@end
3 changes: 3 additions & 0 deletions Couch/CouchResource.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ - (CouchDatabase*) database {
// No, this is not an infinite regress. CouchDatabase overrides this to return self.
}

- (BOOL) exists {
return (BOOL)[[self HEAD] wait];
}

- (NSError*) operation: (RESTOperation*)op willCompleteWithError: (NSError*)error {
error = [super operation: op willCompleteWithError: error];
Expand Down
51 changes: 51 additions & 0 deletions Couch/CouchSecurity.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// CouchSecurity.h
// CouchCocoa
//
// Created by Fabien Franzen on 20-06-12.
// Copyright (c) 2012 Couchbase, Inc. All rights reserved.
//
// For more info: http://wiki.apache.org/couchdb/Security_Features_Overview
//

#import "CouchDynamicObject.h"


static NSString* const kSecurityAdminNamesKey = @"adminNames";
static NSString* const kSecurityAdminRolesKey = @"adminRoles";

static NSString* const kSecurityReaderNamesKey = @"readerNames";
static NSString* const kSecurityReaderRolesKey = @"readerRoles";

@class CouchUser, CouchResource, RESTOperation;

@interface CouchSecurity : CouchDynamicObject
{
CouchResource* _resource;
NSMutableDictionary* _properties;
}

@property (readonly) NSDictionary* properties;

/** Admins: can create/update Design Documents and manipulate the (per db) Couch Security Object.
However, they cannot create or delete a database. **/
@property (copy,readwrite) NSArray* adminNames;
@property (copy,readwrite) NSArray* adminRoles;

/** Readers: can read and also create//update/delete documents (when validation permits),
but are not allowed to create/update Design Documents. **/
@property (copy,readwrite) NSArray* readerNames;
@property (copy,readwrite) NSArray* readerRoles;

/** The dropbox value is supported on Refuge and rcouch:
https://github.com/refuge/couch_core/commit/742846156eb5b881f88b88c6deecbef4e66ed2a0 **/
@property (readwrite) BOOL dropBox;

/** Save the current settings to the database. **/
- (RESTOperation*)update;

/** Helper methods to work with the nested collections of names and roles. **/
- (void)addObject:(id)obj forProperty:(NSString *)property;
- (void)removeObject:(id)obj forProperty:(NSString *)property;

@end
119 changes: 119 additions & 0 deletions Couch/CouchSecurity.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// CouchSecurity.m
// CouchCocoa
//
// Created by Fabien Franzen on 20-06-12.
// Copyright (c) 2012 Couchbase, Inc. All rights reserved.
//

#import "CouchSecurity.h"
#import "CouchUser.h"
#import "CouchInternal.h"

@interface CouchSecurity ()
- (BOOL)load;
@end

@implementation CouchSecurity

- (id)initWithDatabase: (CouchDatabase*)database {
self = [super init];
if(self) {
_resource = [[CouchResource alloc] initWithParent:database relativePath: @"_security"];
[_resource retain];
}
return self;
}

@dynamic adminNames, adminRoles, readerNames, readerRoles, dropBox;

- (void)dealloc {
[_resource release];
[_properties release];
[super dealloc];
}

- (NSString*)keyPathForProperty:(NSString*)key {
static NSDictionary* mapping = nil;
if (mapping == nil) {
mapping = [NSDictionary dictionaryWithObjectsAndKeys:
@"admins.names", kSecurityAdminNamesKey,
@"admins.roles", kSecurityAdminRolesKey,
@"readers.names", kSecurityReaderNamesKey,
@"readers.roles", kSecurityReaderRolesKey,
nil];
}
return [mapping objectForKey:key];
}

- (id) getValueOfProperty: (NSString*)property {
NSString* keyPath = [self keyPathForProperty:property];
if (!keyPath) keyPath = property;
return [self.properties valueForKeyPath:keyPath];
}

- (BOOL) setValue: (id)value ofProperty: (NSString*)property {
NSString* keyPath = [self keyPathForProperty:property];
if (!keyPath) keyPath = property;
[self.properties setValue:value forKeyPath:keyPath];
return YES;
}

- (void)addObject:(id)obj forProperty:(NSString *)property {
id prop = [self getValueOfProperty:property];
if ([prop respondsToSelector:@selector(addObject:)]) {
if (![prop containsObject:obj]) [prop addObject:obj];
}
}

- (void)removeObject:(id)obj forProperty:(NSString *)property {
id prop = [self getValueOfProperty:property];
if ([prop respondsToSelector:@selector(removeObject:)]) {
[prop removeObject:obj];
}
}

- (NSDictionary *)properties {
if (!_properties) {
_properties = [[NSMutableDictionary dictionary] retain];
[_properties setValue:[NSMutableDictionary dictionary] forKey:@"admins"];
[_properties setValue:[NSMutableDictionary dictionary] forKey:@"readers"];
[_properties setValue:[NSMutableArray array] forKeyPath:@"admins.names"];
[_properties setValue:[NSMutableArray array] forKeyPath:@"admins.roles"];
[_properties setValue:[NSMutableArray array] forKeyPath:@"readers.names"];
[_properties setValue:[NSMutableArray array] forKeyPath:@"readers.roles"];
[self load];
}
return _properties;
}

- (RESTOperation*)update {
return [_resource PUTJSON: self.properties parameters: nil];
}

- (BOOL)load {
RESTOperation* op = [_resource GET];
if ([op wait]) {
NSDictionary* response = $castIf(NSDictionary, op.responseBody.fromJSON);
if (response && response.count > 0) {
NSSet *writableNames = [self.class writablePropertyNames];
[writableNames enumerateObjectsUsingBlock:^(id key, BOOL *stop) {
NSString* keyPath = [self keyPathForProperty:key];
if (!keyPath) keyPath = key;
id value = [response valueForKeyPath:keyPath];
if ([[self.class classOfProperty:key] isSubclassOfClass:[NSArray class]]) {
if (value) {
value = [[value mutableCopy] autorelease];
} else {
value = [NSMutableArray array];
}
}
[self.properties setValue:value forKeyPath:keyPath];
}];
}
return YES;
}
return NO;
}

@end
18 changes: 17 additions & 1 deletion Couch/CouchServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// and limitations under the License.

#import "CouchResource.h"
@class CouchDatabase, CouchLiveQuery, CouchPersistentReplication, RESTCache;
@class CouchDatabase, CouchLiveQuery, CouchPersistentReplication, CouchUser, RESTCache;


/** The top level of a CouchDB server. Contains CouchDatabases. */
Expand All @@ -28,6 +28,7 @@
RESTOperation* _activeTasksOp;
NSTimer* _activityPollTimer;
CouchLiveQuery* _replicationsQuery;
CouchLiveQuery* _usersQuery;
}

/** Initialize given a server URL. */
Expand Down Expand Up @@ -66,10 +67,25 @@

#pragma mark - REPLICATION:

/** This is the server-wide _replicators database **/
@property (readonly) CouchDatabase* replicatorDatabase;

/** All currently defined CouchPersistentReplications (as stored in the replicator database.)
To create a replication, use the methods on CouchDatabase. */
@property (readonly) NSArray* replications;

#pragma mark - USERS:

/** This is the server-wide _users database **/
@property (readonly) CouchDatabase* usersDatabase;

/** All currently defined CouchUsers (as stored in the _users database.)
To create a user, use userWithName and the CouchUser methods. */
@property (readonly) NSArray* users;

/** Will get a CouchUser with the correct document ID for the given name. **/
- (CouchUser*)userWithName:(NSString*)name;

@end


Expand Down
Loading