]> err.no Git - scalable-opengroupware.org/blob - SoObjects/SOGo/SOGoUser.m
0197ca9399eb66691049ddddfd9836124c09e3db
[scalable-opengroupware.org] / SoObjects / SOGo / SOGoUser.m
1 /*
2   Copyright (C) 2005 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #import <Foundation/NSArray.h>
23 #import <Foundation/NSNull.h>
24 #import <Foundation/NSTimeZone.h>
25 #import <Foundation/NSUserDefaults.h>
26 #import <Foundation/NSValue.h>
27 #import <NGObjWeb/WOApplication.h>
28 #import <NGObjWeb/WOContext.h>
29 #import <NGObjWeb/WORequest.h>
30 #import <NGObjWeb/SoObject.h>
31 #import <NGExtensions/NSNull+misc.h>
32
33 #import "AgenorUserDefaults.h"
34 #import "LDAPUserManager.h"
35 #import "SOGoDateFormatter.h"
36 #import "SOGoObject.h"
37 #import "SOGoPermissions.h"
38 #import "NSArray+Utilities.h"
39
40 #import "SOGoUser.h"
41
42 static NSTimeZone *serverTimeZone = nil;
43 static NSString *fallbackIMAP4Server = nil;
44 static NSString *defaultLanguage = nil;
45 static NSString *superUsername = nil;
46 static NSURL *AgenorProfileURL = nil;
47 static BOOL acceptAnyUser = NO;
48
49 NSString *SOGoWeekStartHideWeekNumbers = @"HideWeekNumbers";
50 NSString *SOGoWeekStartJanuary1 = @"January1";
51 NSString *SOGoWeekStartFirst4DayWeek = @"First4DayWeek";
52 NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
53
54 @interface NSObject (SOGoRoles)
55
56 - (NSArray *) rolesOfUser: (NSString *) uid;
57
58 @end
59
60 @implementation SOGoUser
61
62 + (void) initialize
63 {
64   NSString *tzName, *nsUsername;
65   NSUserDefaults *ud;
66   NSString *profileURL;
67
68   ud = [NSUserDefaults standardUserDefaults];
69   if (!serverTimeZone)
70     {
71       tzName = [ud stringForKey: @"SOGoServerTimeZone"];
72       if (!tzName)
73         tzName = @"UTC";
74       serverTimeZone = [NSTimeZone timeZoneWithName: tzName];
75       [serverTimeZone retain];
76     }
77   if (!AgenorProfileURL)
78     {
79       profileURL = [ud stringForKey: @"AgenorProfileURL"];
80       AgenorProfileURL = [[NSURL alloc] initWithString: profileURL];
81     }
82   if (!fallbackIMAP4Server)
83     ASSIGN (fallbackIMAP4Server,
84             [ud stringForKey: @"SOGoFallbackIMAP4Server"]);
85   if (!defaultLanguage)
86     {
87       ASSIGN (defaultLanguage, [ud stringForKey: @"SOGoDefaultLanguage"]);
88       if (!defaultLanguage)
89         ASSIGN (defaultLanguage, @"English");
90     }
91   if (!superUsername)
92     {
93       nsUsername = [ud stringForKey: @"SOGoSuperUsername"];
94       if ([nsUsername length] > 0)
95         ASSIGN (superUsername, nsUsername);
96     }
97
98   acceptAnyUser = ([[ud stringForKey: @"SOGoAuthentificationMethod"]
99                      isEqualToString: @"bypass"]);
100 }
101
102 + (SOGoUser *) userWithLogin: (NSString *) newLogin
103                        roles: (NSArray *) newRoles
104 {
105   SOGoUser *user;
106
107   user = [[self alloc] initWithLogin: newLogin roles: newRoles];
108   [user autorelease];
109
110   return user;
111 }
112
113 - (id) init
114 {
115   if ((self = [super init]))
116     {
117       userDefaults = nil;
118       userSettings = nil;
119       allEmails = nil;
120       language = nil;
121       currentPassword = nil;
122       dateFormatter = nil;
123     }
124
125   return self;
126 }
127
128 - (id) initWithLogin: (NSString *) newLogin
129                roles: (NSArray *) newRoles
130 {
131   LDAPUserManager *um;
132   NSString *realUID;
133
134   if (acceptAnyUser
135       || [newLogin isEqualToString: @"anonymous"]
136       || [newLogin isEqualToString: @"freebusy"])
137     realUID = newLogin;
138   else
139     {
140       um = [LDAPUserManager sharedUserManager];
141       realUID = [[um contactInfosForUserWithUIDorEmail: newLogin]
142                   objectForKey: @"c_uid"];
143     }
144   self = [super initWithLogin: realUID roles: newRoles];
145
146   return self;
147 }
148
149 - (void) dealloc
150 {
151   [currentPassword release];
152   [userDefaults release];
153   [userSettings release];
154   [allEmails release];
155   [language release];
156   [dateFormatter release];
157   [super dealloc];
158 }
159
160 - (void) setCurrentPassword: (NSString *) newPassword
161 {
162   ASSIGN (currentPassword, newPassword);
163 }
164
165 - (NSString *) currentPassword
166 {
167   return currentPassword;
168 }
169
170 - (id) _fetchFieldForUser: (NSString *) field
171 {
172   NSDictionary *contactInfos;
173   LDAPUserManager *um;
174
175   um = [LDAPUserManager sharedUserManager];
176   contactInfos = [um contactInfosForUserWithUIDorEmail: login];
177
178   return [contactInfos objectForKey: field];
179 }
180
181 - (void) _fetchAllEmails
182 {
183   allEmails = [self _fetchFieldForUser: @"emails"];
184   [allEmails retain];
185 }
186
187 - (void) _fetchCN
188 {
189   cn = [self _fetchFieldForUser: @"cn"];
190   [cn retain];
191 }
192
193 /* properties */
194
195 // - (NSString *) fullEmail
196 // {
197 //   return [[LDAPUserManager sharedUserManager] getFullEmailForUID: login];
198 // }
199
200 // - (NSString *) primaryEmail
201 // {
202 //   if (!allEmails)
203 //     [self _fetchAllEmails];
204
205 //   return [allEmails objectAtIndex: 0];
206 // }
207
208 - (NSArray *) allEmails
209 {
210   if (!allEmails)
211     [self _fetchAllEmails];
212
213   return allEmails;  
214 }
215
216 - (NSString *) systemEmail
217 {
218   if (!allEmails)
219     [self _fetchAllEmails];
220
221   return [allEmails lastObject];
222 }
223
224 - (BOOL) hasEmail: (NSString *) email
225 {
226   if (!allEmails)
227     [self _fetchAllEmails];
228   
229   return [allEmails containsCaseInsensitiveString: email];
230 }
231
232 - (NSString *) cn
233 {
234   if (!cn)
235     [self _fetchCN];
236
237   return cn;
238 }
239
240 // - (NSString *) primaryMailServer
241 // {
242 //   return [[self userManager] getServerForUID: [self login]];
243 // }
244
245 // - (NSArray *) additionalIMAP4AccountStrings
246 // {
247 //   return [[self userManager]getSharedMailboxAccountStringsForUID: [self login]];
248 // }
249
250 // - (NSArray *) additionalEMailAddresses
251 // {
252 //   return [[self userManager] getSharedMailboxEMailsForUID: [self login]];
253 // }
254
255 // - (NSDictionary *) additionalIMAP4AccountsAndEMails
256 // {
257 //   return [[self userManager] getSharedMailboxesAndEMailsForUID: [self login]];
258 // }
259
260 - (NSURL *) freeBusyURL
261 {
262   return nil;
263 }
264
265 - (SOGoDateFormatter *) dateFormatterInContext: (WOContext *) context
266 {
267   NSString *format;
268   NSUserDefaults *ud;
269
270   if (!dateFormatter)
271     {
272       dateFormatter = [SOGoDateFormatter new];
273       [dateFormatter setLocale: [context valueForKey: @"locale"]];
274       ud = [self userDefaults];
275       format = [ud stringForKey: @"ShortDateFormat"];
276       if (format)
277         [dateFormatter setShortDateFormat: format];
278       format = [ud stringForKey: @"LongDateFormat"];
279       if (format)
280         [dateFormatter setLongDateFormat: format];
281       format = [ud stringForKey: @"TimeFormat"];
282       if (format)
283         [dateFormatter setTimeFormat: format];
284     }
285
286   return dateFormatter;
287 }
288
289 /* defaults */
290
291 - (NSUserDefaults *) userDefaults
292 {
293   if (!userDefaults)
294     userDefaults
295       = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
296                                     uid: login
297                                     fieldName: @"c_defaults"];
298
299   return userDefaults;
300 }
301
302 - (NSUserDefaults *) userSettings
303 {
304   if (!userSettings)
305     userSettings
306       = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
307                                     uid: login
308                                     fieldName: @"c_settings"];
309
310   return userSettings;
311 }
312
313 - (NSString *) language
314 {
315   NSArray *bLanguages;
316   WOContext *context;
317
318   if (!language)
319     {
320       language = [[self userDefaults] stringForKey: @"Language"];
321       if (![language length])
322         {
323           context = [[WOApplication application] context];
324           bLanguages = [[context request] browserLanguages];
325           if ([bLanguages count] > 0)
326             language = [bLanguages objectAtIndex: 0];
327         }
328       if (![language length])
329         language = defaultLanguage;
330       [language retain];
331     }
332
333   return language;
334 }
335
336 - (NSTimeZone *) timeZone
337 {
338   NSString *timeZoneName;
339
340   if (!userTimeZone)
341     {
342       timeZoneName = [[self userDefaults] stringForKey: @"TimeZone"];
343       if ([timeZoneName length] > 0)
344         userTimeZone = [NSTimeZone timeZoneWithName: timeZoneName];
345       if (!userTimeZone)
346         userTimeZone = serverTimeZone;
347       [userTimeZone retain];
348     }
349
350   return userTimeZone;
351 }
352
353 - (NSTimeZone *) serverTimeZone
354 {
355   return serverTimeZone;
356 }
357
358 /* mail */
359 - (NSArray *) mailAccounts
360 {
361 #warning should be implemented with the user defaults interfaces
362   NSMutableDictionary *mailAccount, *identity;
363   NSMutableArray *identities;
364   NSString *name, *fullName;
365
366   if (!mailAccounts)
367     {
368       NSArray *mails;
369       int i;
370
371       mailAccount = [NSMutableDictionary dictionary];
372       name = [NSString stringWithFormat: @"%@@%@", login, fallbackIMAP4Server];
373       [mailAccount setObject: login forKey: @"userName"];
374       [mailAccount setObject: fallbackIMAP4Server forKey: @"serverName"];
375       [mailAccount setObject: name forKey: @"name"];
376
377       identities = [NSMutableArray array];
378       mails = [self allEmails];
379
380       for (i = 0; i < [mails count]; i++)
381         {
382           identity = [NSMutableDictionary dictionary];
383           fullName = [self cn];
384           if (![fullName length])
385             fullName = login;
386           [identity setObject: fullName forKey: @"fullName"];
387           [identity setObject: [mails objectAtIndex: i] forKey: @"email"];
388           
389           if (i == 0) [identity setObject: [NSNumber numberWithBool: YES] forKey: @"isDefault"];
390           [identities addObject: identity];
391         }
392         
393       [mailAccount setObject: identities forKey: @"identities"];
394
395       mailAccounts = [NSMutableArray new];
396       [mailAccounts addObject: mailAccount];
397     }
398
399   return mailAccounts;
400 }
401
402 /*
403 @interface SOGoMailIdentity : NSObject
404 {
405   NSString *name;
406   NSString *email;
407   NSString *replyTo;
408   NSString *organization;
409   NSString *signature;
410   NSString *vCard;
411   NSString *sentFolderName;
412   NSString *sentBCC;
413   NSString *draftsFolderName;
414   NSString *templatesFolderName;
415   struct
416   {
417     int composeHTML:1;
418     int reserved:31;
419   } idFlags;
420 }
421
422 - (void) setName: (NSString *) _value;
423 - (NSString *) name;
424
425 - (void) setEmail: (NSString *) _value;
426 - (NSString *) email;
427
428 - (void) setReplyTo: (NSString *) _value;
429 - (NSString *) replyTo;
430
431 - (void) setOrganization: (NSString *) _value;
432 - (NSString *) organization;
433
434 - (void) setSignature: (NSString *) _value;
435 - (NSString *) signature;
436 - (BOOL) hasSignature;
437
438 - (void) setVCard: (NSString *) _value;
439 - (NSString *) vCard;
440 - (BOOL) hasVCard;
441
442 - (void) setSentFolderName: (NSString *) _value;
443 - (NSString *) sentFolderName;
444
445 - (void) setSentBCC: (NSString *) _value;
446 - (NSString *) sentBCC;
447
448 - (void) setDraftsFolderName: (NSString *) _value;
449 - (NSString *) draftsFolderName;
450
451 - (void) setTemplatesFolderName: (NSString *) _value;
452 - (NSString *) templatesFolderName;
453
454 @end */
455
456 - (NSArray *) allIdentities
457 {
458   NSArray *identities;
459
460   [self mailAccounts];
461   identities = [mailAccounts objectsForKey: @"identities"];
462
463   return [identities flattenedArray];
464 }
465
466 - (NSDictionary *) primaryIdentity
467 {
468   NSDictionary *defaultAccount;
469
470   [self mailAccounts];
471   defaultAccount = [mailAccounts objectAtIndex: 0];
472
473   return [[defaultAccount objectForKey: @"identities"] objectAtIndex: 0];
474 }
475
476 - (NSString *) messageForwarding
477 {
478   NSString *messageForwarding;
479
480   messageForwarding
481     = [[self userDefaults] stringForKey: @"MessageForwarding"];
482   if (![messageForwarding length])
483     messageForwarding = @"attached";
484
485   return messageForwarding;
486 }
487
488 /* folders */
489
490 // TODO: those methods should check whether the traversal stack in the context
491 //       already contains proper folders to improve caching behaviour
492
493 - (id) homeFolderInContext: (id) _ctx
494 {
495   /* Note: watch out for cyclic references */
496   // TODO: maybe we should add an [activeUser reset] method to SOPE
497   id folder;
498   
499   folder = [(WOContext *)_ctx objectForKey:@"ActiveUserHomeFolder"];
500   if (folder != nil)
501     return [folder isNotNull] ? folder : nil;
502   
503   folder = [[WOApplication application] lookupName: [self login]
504                                         inContext: _ctx
505                                         acquire: NO];
506   if ([folder isKindOfClass:[NSException class]])
507     return folder;
508   
509   [(WOContext *)_ctx setObject: ((folder)
510                                  ? folder
511                                  : (id)[NSNull null])
512                 forKey: @"ActiveUserHomeFolder"];
513   return folder;
514 }
515
516 // - (id) schedulingCalendarInContext: (id) _ctx
517 // {
518 //   /* Note: watch out for cyclic references */
519 //   id folder;
520
521 //   folder = [(WOContext *)_ctx objectForKey:@"ActiveUserCalendar"];
522 //   if (folder != nil)
523 //     return [folder isNotNull] ? folder : nil;
524
525 //   folder = [self homeFolderInContext:_ctx];
526 //   if ([folder isKindOfClass:[NSException class]])
527 //     return folder;
528   
529 //   folder = [folder lookupName:@"Calendar" inContext:_ctx acquire:NO];
530 //   if ([folder isKindOfClass:[NSException class]])
531 //     return folder;
532   
533 //   [(WOContext *)_ctx setObject:folder ? folder : [NSNull null] 
534 //                 forKey:@"ActiveUserCalendar"];
535 //   return folder;
536 // }
537
538 - (NSArray *) rolesForObject: (NSObject *) object
539                    inContext: (WOContext *) context
540 {
541   NSMutableArray *rolesForObject;
542   NSArray *sogoRoles;
543
544   rolesForObject = [NSMutableArray new];
545   [rolesForObject autorelease];
546
547   sogoRoles = [super rolesForObject: object inContext: context];
548   if (sogoRoles)
549     [rolesForObject addObjectsFromArray: sogoRoles];
550
551   if ((superUsername && [login isEqualToString: superUsername])
552       || [[object ownerInContext: context] isEqualToString: login])
553     [rolesForObject addObject: SoRole_Owner];
554   if ([object isKindOfClass: [SOGoObject class]])
555     {
556       sogoRoles = [(SOGoObject *) object aclsForUser: login];
557       if (sogoRoles)
558         [rolesForObject addObjectsFromArray: sogoRoles];
559     }
560
561   return rolesForObject;
562 }
563
564 @end /* SOGoUser */