Compare commits

..
57 changed files with 433 additions and 3316 deletions

No files matched your search

+2 -4
View File
@@ -437,8 +437,8 @@ Defaults to `300`.
|S |SOGoAuthenticationType
|Parameter used to define the way by which users will be authenticated.
For C.A.S., specify `cas`. For SAML2, specify `saml2`. For opendID Connect, specify `openid`.
For anything else, leave that value empty.
For C.A.S., specify `cas`. For SAML2, specify `saml2`. For anything
else, leave that value empty.
|S |SOGoTrustProxyAuthentication
|Parameter used to set whether HTTP username should be trusted.
@@ -815,8 +815,6 @@ Obiously, if your users can connect without specifying a domain, let this parame
|S |SOGoDomainAllowed
|Parameter used to define which domains SOGo should allowed during a connection request. This parameter is an array of strings.
|S |SOGoURLCreateAccount
|Add a link below the login form and set the link using the value of this setting.
|S |SOGoPasswordRecoveryEnabled
|Boolean enable password recovery with secret question or secondary e-mail. Default value is `NO`.
+11 -17
View File
@@ -288,16 +288,16 @@ static BOOL debugLeaks;
e = [urlStrings objectEnumerator];
while (ok && (tmp = [e nextObject]))
{
value = [defaults stringForKey: tmp];
if (value)
[self _checkTableWithCM: cm tableURL: value andType: tmp];
else
{
[self errorWithFormat: @"No value specified for '%@'", tmp];
ok = NO;
value = [defaults stringForKey: tmp];
if (value)
[self _checkTableWithCM: cm tableURL: value andType: tmp];
else
{
[self errorWithFormat: @"No value specified for '%@'", tmp];
ok = NO;
}
}
}
if (combined)
{
@@ -322,15 +322,9 @@ static BOOL debugLeaks;
// Create the email alarms table, if required
if ([defaults enableEMailAlarms])
{
[[fm alarmsFolder] createFolderIfNotExists];
}
//Create mandatory openId table, if used
if([defaults hasOpenIdType])
{
[[fm openIdFolder] createFolderIfNotExists];
}
{
[[fm alarmsFolder] createFolderIfNotExists];
}
}
return ok;
+1 -4
View File
@@ -31,7 +31,7 @@
*/
@class NSString, NSArray, NSURL, NSDictionary, NSException;
@class GCSChannelManager, GCSAlarmsFolder, GCSAdminFolder, GCSFolder, GCSFolderType, GCSSessionsFolder, GCSOpenIdFolder;
@class GCSChannelManager, GCSAlarmsFolder, GCSAdminFolder, GCSFolder, GCSFolderType, GCSSessionsFolder;
@interface GCSFolderManager : NSObject
{
@@ -92,9 +92,6 @@
/* admin */
- (GCSAdminFolder *)adminFolder;
/* openid */
- (GCSOpenIdFolder *) openIdFolder;
/* folder types */
- (GCSFolderType *)folderTypeWithName:(NSString *)_name;
-7
View File
@@ -38,7 +38,6 @@
#import "EOAdaptorChannel+GCS.h"
#import "GCSAlarmsFolder.h"
#import "GCSAdminFolder.h"
#import "GCSOpenIdFolder.h"
#import "GCSFolder.h"
#import "GCSFolderType.h"
#import "GCSSessionsFolder.h"
@@ -505,12 +504,6 @@ static BOOL _singleStoreMode = NO;
return [GCSAdminFolder adminFolderWithFolderManager: self];
}
/* openId */
- (GCSOpenIdFolder *) openIdFolder
{
return [GCSOpenIdFolder openIdFolderWithFolderManager: self];
}
- (NSString *)generateSQLWhereForInternalNames:(NSArray *)_names
exactMatch:(BOOL)_beExact orDirectSubfolderMatch:(BOOL)_directSubs
{
-57
View File
@@ -1,57 +0,0 @@
/* GCSAdminFolder.h - this file is part of $PROJECT_NAME_HERE$
*
* Copyright (C) 2023 Alinto
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef GCSOPENIDFOLDER_H
#define GCSOPENIDOLDER_H
@class NSCalendarDate;
@class NSException;
@class NSNumber;
@class NSString;
@class GCSFolderManager;
@interface GCSOpenIdFolder : NSObject
{
GCSFolderManager *folderManager;
}
+ (id)openIdFolderWithFolderManager:(GCSFolderManager *)newFolderManager;
- (void) setFolderManager: (GCSFolderManager *) newFolderManager;
/* operations */
- (void) createFolderIfNotExists;
- (BOOL) canConnectStore;
- (NSString *) getRefreshToken: (NSString *) _user_session useOldSession: (BOOL) use_old_session;
- (NSString *) getNewToken: (NSString *) _old_session;
- (NSException *) writeOpenIdSession: (NSString *) _user_session
withOldSession: (NSString *) _old_session
withRefreshToken: (NSString *) _refresh_token
withExpire: (NSNumber *) _expire
withRefreshExpire: (NSNumber *) _refresh_expire;
- (NSException *) deleteOpenIdSessionFor: (NSString *) _user_session;
@end
#endif /* GCSALARMSFOLDER_H */
-363
View File
@@ -1,363 +0,0 @@
/* GCSAdminFolder.m - this file is part of SOGo
*
* Copyright (C) 2023 Alinto
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSNull+misc.h>
#import <GDLAccess/EOAdaptorContext.h>
#import <GDLAccess/EOAttribute.h>
#import <GDLAccess/EOEntity.h>
#import <GDLAccess/EOSQLQualifier.h>
#import "EOQualifier+GCS.h"
#import "GCSChannelManager.h"
#import "GCSFolderManager.h"
#import "GCSSpecialQueries.h"
#import "NSURL+GCS.h"
#import "GCSOpenIdFolder.h"
static NSString *openIdFolderURLString = nil;
#warning GCSOpenIdFolder should share a common ancestor with GCSFolder
@implementation GCSOpenIdFolder
+ (void) initialize
{
NSUserDefaults *ud;
if (!openIdFolderURLString)
{
ud = [NSUserDefaults standardUserDefaults];
ASSIGN (openIdFolderURLString, [ud stringForKey: @"OCSOpenIdURL"]);
}
}
+ (id) openIdFolderWithFolderManager: (GCSFolderManager *) newFolderManager
{
GCSOpenIdFolder *newFolder;
if (openIdFolderURLString)
{
newFolder = [self new];
[newFolder autorelease];
[newFolder setFolderManager: newFolderManager];
}
else
{
[self errorWithFormat: @"'OCSOpenIdURL' is not set"];
newFolder = nil;
}
return newFolder;
}
- (void) setFolderManager: (GCSFolderManager *) newFolderManager
{
ASSIGN (folderManager, newFolderManager);
}
/* accessors */
- (NSURL *) _location
{
NSURL *location;
if (openIdFolderURLString)
location = [NSURL URLWithString: openIdFolderURLString];
else
{
[self warnWithFormat: @"'OCSOpenIdURL' is not set"];
location = nil;
}
return location;
}
- (GCSChannelManager *) _channelManager
{
return [folderManager channelManager];
}
- (NSString *) _storeTableName
{
return [[self _location] gcsTableName];
}
- (EOEntity *) _storeTableEntityForChannel: (EOAdaptorChannel *) tc
{
static EOEntity *entity = nil;
EOAttribute *attribute;
NSString *tableName;
NSString *columns[] = {@"c_user_session", @"c_old_session", @"c_session_started", @"c_refresh_token", @"c_access_token_expires_in", @"c_refresh_token_expires_in", nil };
NSString **column;
NSMutableArray *keys;
NSDictionary *types;
if (!entity)
{
entity = [EOEntity new];
tableName = [self _storeTableName];
[entity setName: tableName];
[entity setExternalName: tableName];
types = [[tc specialQueries] openIdAttributeTypes];
column = columns;
while (*column)
{
attribute = [EOAttribute new];
[attribute setName: *column];
[attribute setColumnName: *column];
[attribute setExternalType: [types objectForKey: *column]];
[entity addAttribute: attribute];
[attribute release];
column++;
}
keys = [NSMutableArray arrayWithCapacity: 1];
[keys addObject: [entity attributeNamed: @"c_user_session"]];
[entity setPrimaryKeyAttributes: keys];
keys = [NSMutableArray arrayWithCapacity: 5];
[keys addObject: [entity attributeNamed: @"c_old_session"]];
[keys addObject: [entity attributeNamed: @"c_session_started"]];
[keys addObject: [entity attributeNamed: @"c_refresh_token"]];
[keys addObject: [entity attributeNamed: @"c_access_token_expires_in"]];
[keys addObject: [entity attributeNamed: @"c_refresh_token_expires_in"]];
[entity setClassProperties: keys];
[entity setAttributesUsedForLocking: [NSArray array]];
}
return entity;
}
/* connection */
- (EOAdaptorChannel *) _acquireStoreChannel
{
return [[self _channelManager] acquireOpenChannelForURL: [self _location]];
}
- (void) _releaseChannel: (EOAdaptorChannel *) _channel
{
[[self _channelManager] releaseChannel:_channel immediately: YES];
}
- (BOOL) canConnectStore
{
return [[self _channelManager] canConnect:[self _location]];
}
- (void) createFolderIfNotExists
{
EOAdaptorChannel *tc;
NSString *sql, *tableName;
GCSSpecialQueries *queries;
tc = [self _acquireStoreChannel];
tableName = [self _storeTableName];
queries = [tc specialQueries];
sql = [NSString stringWithFormat: @"SELECT 1 FROM %@ WHERE 1 = 2", tableName];
if ([tc evaluateExpressionX: sql])
{
sql = [queries createOpenIdFolderWithName: tableName];
if (![tc evaluateExpressionX: sql])
[self logWithFormat: @"openid folder table '%@' successfully created!", tableName];
}
else
[tc cancelFetch];
[self _releaseChannel: tc];
}
/* operations */
/* table has the following fields:
c_user_session varchar(255) NOT NULL,
c_session_started int(11) NOT NULL,
c_refresh_token varchar(4096) DEFAULT '',
c_access_token_expires_in int(11) NOT NULL,
c_refresh_token_expires_in int(11) DEFAULT NULL,
*/
- (NSDictionary *) recordForSession: (NSString *) _user_session useOldSession: (BOOL) use_old_session
{
EOAdaptorChannel *tc;
EOAdaptorContext *context;
NSException *error;
NSArray *attrs;
NSDictionary *record;
EOEntity *entity;
EOSQLQualifier *qualifier;
record = nil;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
entity = [self _storeTableEntityForChannel: tc];
if(!use_old_session)
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat: @"c_user_session='%@'", _user_session];
else
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat: @"c_old_session='%@'", _user_session];
[qualifier autorelease];
[context beginTransaction];
error = [tc selectAttributesX: [entity attributesUsedForFetch]
describedByQualifier: qualifier
fetchOrder: nil
lock: NO];
if (error)
[self errorWithFormat:@"%s: cannot execute fetch: %@", __PRETTY_FUNCTION__, error];
else
{
attrs = [tc describeResults: NO];
record = [tc fetchAttributes: attrs withZone: NULL];
[tc cancelFetch];
}
[context rollbackTransaction];
[self _releaseChannel: tc];
}
return record;
}
- (NSString *) getRefreshToken: (NSString *) _user_session
{
NSDictionary *r;
r = [self recordForSession: _user_session useOldSession: NO];
if (r && [r objectForKey:@"c_refresh_token"])
return [r objectForKey:@"c_refresh_token"];
return nil;
}
- (NSString *) getNewToken: (NSString *) _old_session
{
NSDictionary *r;
r = [self recordForSession: _old_session useOldSession: YES];
if (r && [r objectForKey:@"c_user_session"])
return [r objectForKey:@"c_user_session"];
return nil;
}
- (NSException *) writeOpenIdSession: (NSString *) _user_session
withOldSession: (NSString *) _old_session
withRefreshToken: (NSString *) _refresh_token
withExpire: (NSNumber *) _expire
withRefreshExpire: (NSNumber *) _refresh_expire
{
NSDictionary *record, *newRecord;
NSException *error;
NSCalendarDate *nowDate;
int now, nowExpire, nowRefreshExpire;
EOAdaptorChannel *tc;
EOAdaptorContext *context;
EOEntity *entity;
EOSQLQualifier *qualifier;
error = nil;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
nowDate = [NSCalendarDate date];
now = (nowDate ? (int)[nowDate timeIntervalSince1970] : 0);
nowExpire = now + [_expire intValue];
if(_refresh_expire)
nowRefreshExpire = now + [_refresh_expire intValue];
else
nowRefreshExpire = -1;
if(!_old_session)
_old_session = @"";
newRecord = [NSDictionary dictionaryWithObjectsAndKeys: _user_session, @"c_user_session",
_old_session, @"c_old_session",
[NSNumber numberWithInt:now], @"c_session_started",
_refresh_token, @"c_refresh_token",
[NSNumber numberWithInt:nowExpire] , @"c_access_token_expires_in",
[NSNumber numberWithInt:nowRefreshExpire] , @"c_refresh_token_expires_in",
nil];
record = [self recordForSession: _user_session useOldSession: NO];
entity = [self _storeTableEntityForChannel: tc];
[context beginTransaction];
if (!record)
{
//If the session already exist no need to update it as it is unique
error = [tc insertRowX: newRecord forEntity: entity];
}
if (error)
{
[context rollbackTransaction];
[self errorWithFormat:@"%s: cannot write record: %@", __PRETTY_FUNCTION__, error];
}
else
[context commitTransaction];
[self _releaseChannel: tc];
}
return error;
}
- (NSException *) deleteOpenIdSessionFor: (NSString *) _user_session
{
EOAdaptorChannel *tc;
EOAdaptorContext *context;
EOEntity *entity;
EOSQLQualifier *qualifier;
NSException *error;
error = nil;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
entity = [self _storeTableEntityForChannel: tc];
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat: @"c_user_session='%@'",_user_session];
[qualifier autorelease];
[context beginTransaction];
error = [tc deleteRowsDescribedByQualifierX: qualifier];
if (error)
{
[context rollbackTransaction];
[self errorWithFormat:@"%s: cannot delete record: %@", __PRETTY_FUNCTION__, error];
}
else
[context commitTransaction];
[self _releaseChannel: tc];
}
return error;
}
@end
-3
View File
@@ -42,9 +42,6 @@
- (NSString *)createAdminFolderWithName:(NSString *)tableName;
- (NSDictionary *)adminAttributeTypes;
- (NSString *)createOpenIdFolderWithName:(NSString *)tableName;
- (NSDictionary *)openIdAttributeTypes;
- (NSString *) updateCPathInFolderInfo:(NSString *)tableName
withCPath2:(NSString *)c_path2;
-111
View File
@@ -95,21 +95,6 @@
return nil;
}
- (NSString *) createOpenIdFolderWithName: (NSString *) tableName
{
[self subclassResponsibility: _cmd];
return nil;
}
- (NSDictionary *) openIdAttributeTypes
{
[self subclassResponsibility: _cmd];
return nil;
}
- (NSString *) createFolderTableWithName: (NSString *) tableName
{
[self subclassResponsibility: _cmd];
@@ -210,38 +195,6 @@
return types;
}
- (NSString *) createOpenIdFolderWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_user_session VARCHAR(4096) NOT NULL,"
@" c_old_session VARCHAR(4096) NULL,"
@" c_session_started INT4 NOT NULL,"
@" c_refresh_token VARCHAR(4096) NULL,"
@" c_access_token_expires_in INT4 NOT NULL,"
@" c_refresh_token_expires_in INT4 NULL)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
- (NSDictionary *) openIdAttributeTypes
{
static NSMutableDictionary *types = nil;
if (!types)
{
types = [NSMutableDictionary new];
[types setObject: @"varchar" forKey: @"c_user_session"];
[types setObject: @"varchar" forKey: @"c_old_session"];
[types setObject: @"int" forKey: @"c_session_started"];
[types setObject: @"varchar" forKey: @"c_refresh_token"];
[types setObject: @"int" forKey: @"c_access_token_expires_in"];
[types setObject: @"int" forKey: @"c_refresh_token_expires_in"];
}
return types;
}
- (NSString *) createFolderTableWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
@@ -371,38 +324,6 @@
return types;
}
- (NSString *) createOpenIdFolderWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_user_session VARCHAR(4096) NOT NULL,"
@" c_old_session VARCHAR(4096) NULL,"
@" c_session_started INT4 NOT NULL,"
@" c_refresh_token VARCHAR(4096) NULL,"
@" c_access_token_expires_in INT4 NOT NULL,"
@" c_refresh_token_expires_in INT4 NULL)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
- (NSDictionary *) openIdAttributeTypes
{
static NSMutableDictionary *types = nil;
if (!types)
{
types = [NSMutableDictionary new];
[types setObject: @"varchar" forKey: @"c_user_session"];
[types setObject: @"varchar" forKey: @"c_old_session"];
[types setObject: @"int" forKey: @"c_session_started"];
[types setObject: @"varchar" forKey: @"c_refresh_token"];
[types setObject: @"int" forKey: @"c_access_token_expires_in"];
[types setObject: @"int" forKey: @"c_refresh_token_expires_in"];
}
return types;
}
- (NSString *) createFolderTableWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
@@ -532,38 +453,6 @@
return types;
}
- (NSString *) createOpenIdFolderWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_user_session VARCHAR2(4096) NOT NULL,"
@" c_old_session VARCHAR2(4096) NULL,"
@" c_session_started INTEGER NOT NULL,"
@" c_refresh_token VARCHAR2(4096) NULL,"
@" c_access_token_expires_in INTEGER NOT NULL,"
@" c_refresh_token_expires_in INTEGER NULL)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
- (NSDictionary *) openIdAttributeTypes
{
static NSMutableDictionary *types = nil;
if (!types)
{
types = [NSMutableDictionary new];
[types setObject: @"varchar2" forKey: @"c_user_session"];
[types setObject: @"varchar2" forKey: @"c_old_session"];
[types setObject: @"integer" forKey: @"c_session_started"];
[types setObject: @"varchar2" forKey: @"c_refresh_token"];
[types setObject: @"integer" forKey: @"c_access_token_expires_in"];
[types setObject: @"integer" forKey: @"c_refresh_token_expires_in"];
}
return types;
}
- (NSString *) createFolderTableWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
+4 -6
View File
@@ -28,14 +28,13 @@ libGDLContentStore_HEADER_FILES += \
GCSAdminFolder.h \
GCSContext.h \
GCSFieldInfo.h \
GCSFolder.h \
GCSFolder.h \
GCSFolderManager.h \
GCSFolderType.h \
GCSChannelManager.h \
GCSOpenIdFolder.h \
GCSSessionsFolder.h \
GCSSpecialQueries.h \
GCSStringFormatter.h \
GCSStringFormatter.h \
libGDLContentStore_OBJC_FILES += \
NSURL+GCS.m \
@@ -46,14 +45,13 @@ libGDLContentStore_OBJC_FILES += \
GCSAdminFolder.m \
GCSContext.m \
GCSFieldInfo.m \
GCSFolder.m \
GCSFolder.m \
GCSFolderManager.m \
GCSFolderType.m \
GCSChannelManager.m \
GCSOpenIdFolder.m \
GCSSessionsFolder.m \
GCSSpecialQueries.m \
GCSStringFormatter.m \
GCSStringFormatter.m \
# framework support
-10
View File
@@ -165,16 +165,6 @@ CREATE TABLE sogo_admin (
PRIMARY KEY (c_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
CREATE TABLE sogo_opend_id (
c_user_session varchar(4096) NOT NULL,
c_old_session varchar(4096) DEFAULT '',
c_session_started int(11) NOT NULL,
c_refresh_token varchar(4096) DEFAULT '',
c_access_token_expires_in int(11) NOT NULL,
c_refresh_token_expires_in int(11) DEFAULT NULL,
PRIMARY KEY (c_user_session)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
CREATE TABLE sogo_user_profile (
c_uid varchar(255) NOT NULL,
c_defaults longtext,
@@ -379,7 +379,7 @@ NSNumber *iCalDistantFutureNumber = nil;
currentAttendee = [attendees nextObject];
while (!isAttendee
&& currentAttendee)
if ([user hasEmail: [currentAttendee rfc822Email]])
if ([user hasEmail: [currentAttendee rfc822Email]] && ![self isOrganizer:[currentAttendee rfc822Email]]) // Exclude organizer if in attendees
isAttendee = YES;
else
currentAttendee = [attendees nextObject];
+1 -8
View File
@@ -291,7 +291,6 @@ static NSString *userAgent = nil;
{
[headers setObject: @"true" forKey: @"receipt"];
[headers setObject: receipt forKey: @"Disposition-Notification-To"];
[headers setObject: receipt forKey: @"Return-Receipt-To"];
}
else
{
@@ -303,14 +302,12 @@ static NSString *userAgent = nil;
if (pureSender)
{
[headers setObject: pureSender forKey: @"Disposition-Notification-To"];
[headers setObject: pureSender forKey: @"Return-Receipt-To"];
}
}
else
{
[headers removeObjectForKey: @"receipt"];
[headers removeObjectForKey: @"Disposition-Notification-To"];
[headers removeObjectForKey: @"Return-Receipt-To"];
}
}
}
@@ -1045,10 +1042,8 @@ static NSString *userAgent = nil;
if ([priority isNotEmpty] && [priority isKindOfClass: [NSString class]])
[info setObject: (NSString*)priority forKey: @"X-Priority"];
receipt = [h objectForKey: @"disposition-notification-to"];
if ([receipt isNotEmpty] && [receipt isKindOfClass: [NSString class]]) {
if ([receipt isNotEmpty] && [receipt isKindOfClass: [NSString class]])
[info setObject: (NSString*)receipt forKey: @"Disposition-Notification-To"];
[info setObject: (NSString*)receipt forKey: @"Return-Receipt-To"];
}
ud = [[context activeUser] userDefaults];
@@ -1898,8 +1893,6 @@ static NSString *userAgent = nil;
[map setObject: s forKey: @"X-Priority"];
if ([(s = [headers objectForKey: @"Disposition-Notification-To"]) length] > 0)
[map setObject: s forKey: @"Disposition-Notification-To"];
if ([(s = [headers objectForKey: @"Return-Receipt-To"]) length] > 0)
[map setObject: s forKey: @"Return-Receipt-To"];
[self _addHeaders: _headers toHeaderMap: map];
+13 -24
View File
@@ -132,24 +132,14 @@
- (NGImap4ConnectionManager *) mailManager
{
SOGoSystemDefaults *sd;
NSString *imapAuthMech, *domain;
domain = [[[self context] activeUser] loginDomain];
sd = [SOGoSystemDefaults sharedSystemDefaults];
if([sd doesLoginTypeByDomain])
imapAuthMech = [sd getImapAuthMechForDomain: domain];
else
imapAuthMech = nil;
return [NGImap4ConnectionManager defaultConnectionManager: imapAuthMech];
return [NGImap4ConnectionManager defaultConnectionManager];
}
- (NGImap4Connection *) _createIMAP4Connection
{
NGImap4ConnectionManager *manager;
NGImap4Connection *newConnection;
NSString *password, *domain;
NSString *password;
NGInternetSocketAddress *host;
SOGoSystemDefaults *sd;
BOOL usesSSO;
@@ -162,15 +152,12 @@
host = [NGInternetSocketAddress addressWithPort:0 onHost:[[self imap4URL] host]];
sd = [SOGoSystemDefaults sharedSystemDefaults];
domain = [[[self context] activeUser] loginDomain];
usesSSO = [sd isSsoUsed: domain];
usesSSO = [[sd authenticationType] isEqualToString: @"cas"] || [[sd authenticationType] isEqualToString: @"saml2"];
if (![[[self mailAccountFolder] nameInContainer] isEqualToString: @"0"] &&
usesSSO &&
[host isLocalhost])
{
//
[self errorWithFormat: @"Trying to use localhost for additional IMAP account - aborting."];
return nil;
}
@@ -240,17 +227,19 @@
login = [[[self context] activeUser] login];
if (!login)
login = [[[[self container] context] activeUser] login];
login = [[[[self container] context] activeUser] login];
cacheKey = [NSString stringWithFormat: @"%@+%@", login, [[self mailAccountFolder] nameInContainer]];
cacheKey = [NSString stringWithFormat: @"%@+%@",
login,
[[self mailAccountFolder] nameInContainer]];
imap4 = [sogoCache imap4ConnectionForKey: cacheKey];
if (!imap4)
{
imap4 = [self _createIMAP4Connection];
[sogoCache registerIMAP4Connection: imap4
forKey: cacheKey];
}
[imap4 retain];
{
imap4 = [self _createIMAP4Connection];
[sogoCache registerIMAP4Connection: imap4
forKey: cacheKey];
}
[imap4 retain];
}
// Connection broken, try to reconnect
-2
View File
@@ -69,7 +69,6 @@ SOGo_HEADER_FILES = \
SOGoAuthenticator.h \
SOGoSession.h \
SOGoCASSession.h \
SOGoOpenIdSession.h \
SOGoDAVAuthenticator.h \
SOGoProxyAuthenticator.h \
SOGoStaticAuthenticator.h \
@@ -162,7 +161,6 @@ SOGo_OBJC_FILES = \
\
SOGoSession.m \
SOGoCASSession.m \
SOGoOpenIdSession.m \
SOGoDAVAuthenticator.m \
SOGoProxyAuthenticator.m \
SOGoStaticAuthenticator.m \
-1
View File
@@ -17,7 +17,6 @@ SOGo_LIBRARIES_DEPEND_UPON += \
-Wl,--no-as-needed \
-L../../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
-lmemcached \
-lcurl \
-lGDLAccess \
-lNGObjWeb \
-lNGCards \
+4 -2
View File
@@ -2364,7 +2364,8 @@ _makeLDAPChanges (NGLdapConnection *ldapConnection,
[pool release];
continue; //user alrady fetch
}
[userLogins addObject: login];
if(login != nil)
[userLogins addObject: login];
user = [SOGoUser userWithLogin: login roles: nil];
if (user)
{
@@ -2397,7 +2398,8 @@ _makeLDAPChanges (NGLdapConnection *ldapConnection,
[pool release];
continue; //user alrady fetch
}
[userLogins addObject: login];
if(login != nil)
[userLogins addObject: login];
user = [SOGoUser userWithLogin: login roles: nil];
if (user)
{
-1
View File
@@ -95,7 +95,6 @@
return keysWithFormat;
}
- (NSComparisonResult) caseInsensitiveDisplayNameCompare: (NSDictionary *) theDictionary
{
return [[self objectForKey: @"cn"] caseInsensitiveCompare: [theDictionary objectForKey: @"cn"]];
+1 -4
View File
@@ -80,10 +80,7 @@ static int cssEscapingCount;
{
hostR = [self rangeOfString: @"://"];
locationR = [[self substringFromIndex: (hostR.location + hostR.length)] rangeOfString: @"/"];
if(locationR.location != NSNotFound)
newURL = [self substringFromIndex: (hostR.location + hostR.length + locationR.location)];
else
newURL = @"";
newURL = [self substringFromIndex: (hostR.location + hostR.length + locationR.location)];
}
return newURL;
-7
View File
@@ -119,13 +119,6 @@
- (void) removeCASSessionWithTicket: (NSString *) ticket;
// OpenId Support
- (NSString *) openIdSessionFromServer: (NSString *) endpoint;
- (void) setOpenIdSession: (NSString *) openIdSession
forServer: (NSString *) endpoint;
- (NSString *) userOpendIdSessionFromServer: (NSString *) endpoint;
- (void) setUserOpendIdSessionFromServer: (NSString *) endpoint
nextCheckAfter: (NSString *) nextCheck;
//
// SAML2 support
//
-26
View File
@@ -683,32 +683,6 @@ static memcached_st *handle = NULL;
}
}
// OpenId support
- (NSString *) openIdSessionFromServer: (NSString *) endpoint
{
return [self valueForKey: [NSString stringWithFormat: @"openId:%@", endpoint]];
}
- (void) setOpenIdSession: (NSString *) openIdSession
forServer: (NSString *) endpoint
{
[self setValue: openIdSession
forKey: [NSString stringWithFormat: @"openId:%@", endpoint]];
}
- (NSString *) userOpendIdSessionFromServer: (NSString *) identifier
{
return [self valueForKey: [NSString stringWithFormat: @"userOpenId:%@", identifier]];
}
- (void) setUserOpendIdSessionFromServer: (NSString *) identifier
nextCheckAfter: (NSString *) nextCheck
{
[self setValue: nextCheck
forKey: [NSString stringWithFormat: @"userOpenId:%@", identifier]];
}
//
// SAML2 support
//
-1
View File
@@ -62,7 +62,6 @@ extern NSString *SOGoDefaultsSourceUnmutableSource;
- (void) setBool: (BOOL) value forKey: (NSString *) key;
- (BOOL) boolForKey: (NSString *) key;
- (BOOL) boolForKey: (NSString *) key andDict: (NSDictionary*) _dict;
- (void) setFloat: (float) value forKey: (NSString *) key;
- (float) floatForKey: (NSString *) key;
-23
View File
@@ -164,29 +164,6 @@ static Class NSStringKlass = Nil;
return value;
}
- (BOOL) boolForKey: (NSString *) key andDict: (NSDictionary*) _dict
{
id boolForKey;
BOOL value;
boolForKey = [_dict objectForKey: key];
if (boolForKey)
{
if ([boolForKey respondsToSelector: @selector (boolValue)])
value = [boolForKey boolValue];
else
{
[self warnWithFormat: @"expected a boolean for '%@' (ignored)",
key];
value = NO;
}
}
else
value = NO;
return value;
}
- (void) setFloat: (float) value
forKey: (NSString *) key
{
+5 -11
View File
@@ -266,7 +266,6 @@
systemMessage: (BOOL) isSystemMessage
{
NSString *currentTo, *login, *password;
NSString * smtpAuthMethod;
NSDictionary *currentAcount;
NSMutableArray *toErrors;
NSEnumerator *addresses;
@@ -289,9 +288,7 @@
currentAcount = [[user mailAccounts] objectAtIndex: userId];
//Check if we do an smtp authentication
smtpAuthMethod = authenticationType;
doSmtpAuth = ([smtpAuthMethod isEqualToString: @"plain"] || [smtpAuthMethod isEqualToString: @"xoauth2"])
&& ![authenticator isKindOfClass: [SOGoEmptyAuthenticator class]];
doSmtpAuth = [authenticationType isEqualToString: @"plain"] && ![authenticator isKindOfClass: [SOGoEmptyAuthenticator class]];
if(!doSmtpAuth && userId > 0)
{
doSmtpAuth = [currentAcount objectForKey: @"smtpAuth"] ? [[currentAcount objectForKey: @"smtpAuth"] boolValue] : NO;
@@ -307,7 +304,6 @@
{
login = [currentAcount objectForKey: @"userName"];
password = [currentAcount objectForKey: @"password"];
smtpAuthMethod = "plain"; //Only support plain for auxiliary account
}
else
{
@@ -326,9 +322,8 @@
if (isSystemMessage
&& ![[[SOGoUserManager sharedUserManager] getEmailForUID: [[authenticator userInContext: woContext] loginInDomain]] isEqualToString: sender]
&& smtpMasterUserEnabled) {
if (![client authenticateUser: smtpMasterUserUsername
withPassword: smtpMasterUserPassword
withMethod: smtpAuthMethod]) {
if (![client plainAuthenticateUser: smtpMasterUserUsername
withPassword: smtpMasterUserPassword]) {
result = [NSException exceptionWithHTTPStatus: 500
reason: @"cannot send message:"
@" (smtp) authentication failure"];
@@ -339,9 +334,8 @@
{
if ([login length] == 0
|| [login isEqualToString: @"anonymous"]
|| ![client authenticateUser: login
withPassword: password
withMethod: smtpAuthMethod])
|| ![client plainAuthenticateUser: login
withPassword: password])
result = [NSException exceptionWithHTTPStatus: 500
reason: @"cannot send message:"
@" (smtp) authentication failure"];
-103
View File
@@ -1,103 +0,0 @@
/* SOGoCASSession.h - this file is part of SOGo
*
* Copyright (C) 2000-2023 Alinto.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef SOGOOPENIDSESSION_H
#define SOGOOPENIDSESSION_H
/* implementation of the OpenId Connect as required for a client/proxy:
https://openid.net/developers/how-connect-works/ */
#import <NGObjWeb/WOResponse.h>
#import <SOGo/SOGoObject.h>
@class NSString;
@class NSMutableDictionary;
@class NSURL;
@class NSJSONSerialization;
@interface SOGoOpenIdSession : SOGoObject
{
//For cache
BOOL cacheUpdateNeeded;
int userTokenInterval;
//From sogo.conf
BOOL openIdSessionIsOK;
NSString *openIdConfigUrl;
NSString *openIdScope;
NSString *openIdClient;
NSString *openIdClientSecret;
NSString *openIdEmailParam;
BOOL openIdEnableRefreshToken;
NSString *forDomain;
//From request to well-known/configuration
NSString *authorizationEndpoint;
NSString *tokenEndpoint;
NSString *introspectionEndpoint;
NSString *userinfoEndpoint;
NSString *endSessionEndpoint;
NSString *revocationEndpoint;
//Access token
NSString *accessToken;
NSString *refreshToken;
NSString *idToken;
NSString *tokenType;
NSNumber *expiresIn;
NSNumber *refreshExpiresIn;
}
+ (BOOL) checkUserConfig;
+ (SOGoOpenIdSession *) OpenIdSession: (NSString *) _domain;
+ (SOGoOpenIdSession *) OpenIdSessionWithConfig: (NSDictionary *) _config;
+ (SOGoOpenIdSession *) OpenIdSessionWithToken: (NSString *) token domain: (NSString *) _domain;
+ (SOGoOpenIdSession *) OpenIdSessionWithTokenAndConfig: (NSString *) token config: (NSDictionary *) _config;
+ (void) deleteValueForSessionKey: (NSString *) theSessionKey;
- (void) initialize;
- (void) initializeWithConfig: (NSDictionary *) _config;
- (BOOL) sessionIsOK;
- (WOResponse *) _performOpenIdRequest: (NSString *) endpoint
method: (NSString *) method
headers: (NSDictionary *) headers
body: (NSData *) body;
- (NSMutableDictionary *) fecthConfiguration: (NSString *) _domain;
- (void) setAccessToken;
- (NSString *) getRefreshToken;
- (NSString *) getToken;
- (NSString *) getCurrentToken;
- (NSString *) loginUrl: (NSString *) oldLocation;
- (NSMutableDictionary *) fetchToken: (NSString *) code redirect: (NSString *) oldLocation;
- (NSString *) logoutUrl;
- (NSMutableDictionary *) fetchUserInfo;
- (NSString *) _login;
- (NSString *) login: (NSString *) identifier;
@end
#endif /* SOGOOPENIDSESSION_H */
-784
View File
@@ -1,784 +0,0 @@
/* SOGoCASSession.m - this file is part of SOGo
*
* Copyright (C) 2010-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <NGObjWeb/WOHTTPConnection.h>
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
#import <NGExtensions/NSObject+Logs.h>
#import <SOGo/SOGoUser.h>
#import <GDLContentStore/GCSOpenIdFolder.h>
#import <GDLContentStore/GCSFolderManager.h>
#import "NSDictionary+Utilities.h"
#import "NSString+Utilities.h"
#import "SOGoCache.h"
#import "SOGoSystemDefaults.h"
#import "SOGoOpenIdSession.h"
static BOOL SOGoOpenIDDebugEnabled = YES;
@implementation SOGoOpenIdSession
/// Check if all required parameters to set up a OpenIdSession are in sogo.conf
+ (BOOL) checkUserConfig
{
SOGoSystemDefaults *sd;
if(nil == [[GCSFolderManager defaultFolderManager] openIdFolder])
{
[self errorWithFormat: @"Something wrong with the table defined by OCSOpenIdURL"];
return NO;
}
sd = [SOGoSystemDefaults sharedSystemDefaults];
return ([sd openIdConfigUrl] && [sd openIdScope] && [sd openIdClient] && [sd openIdClientSecret]);
}
- (void) initializeWithConfig: (NSDictionary *) _config
{
SOGoSystemDefaults *sd;
id refreshTokenBool;
if([_config objectForKey: @"SOGoOpenIdConfigUrl"] &&
[_config objectForKey: @"SOGoOpenIdScope"] &&
[_config objectForKey: @"SOGoOpenIdClient"] &&
[_config objectForKey: @"SOGoOpenIdClientSecret"])
{
openIdConfigUrl = [_config objectForKey: @"SOGoOpenIdConfigUrl"];
openIdScope = [_config objectForKey: @"SOGoOpenIdScope"];
openIdClient = [_config objectForKey: @"SOGoOpenIdClient"];
openIdClientSecret = [_config objectForKey: @"SOGoOpenIdClientSecret"];
openIdEmailParam = [_config objectForKey: @"SOGoOpenIdEmailParam"];
openIdEnableRefreshToken = NO;
refreshTokenBool = [_config objectForKey: @"SOGoOpenIdEnableRefreshToken"];
if (refreshTokenBool && [refreshTokenBool respondsToSelector: @selector (boolValue)])
openIdEnableRefreshToken = [refreshTokenBool boolValue];
userTokenInterval = [_config objectForKey: @"SOGoOpenIdTokenCheckInterval"];
[self _loadSessionFromCache: forDomain];
if(cacheUpdateNeeded)
{
[self fecthConfiguration: forDomain];
}
}
else
{
[self errorWithFormat: @"Missing parameters from sogo.conf"];
}
}
- (void) initialize: (NSString*) _domain
{
SOGoSystemDefaults *sd;
NSDictionary *config;
NSString *type;
sd = [SOGoSystemDefaults sharedSystemDefaults];
SOGoOpenIDDebugEnabled = [sd openIdDebugEnabled];
openIdSessionIsOK = NO;
//Check if there is a root config or config per domain
if(_domain != nil && [sd doesLoginTypeByDomain])
{
forDomain = _domain;
type = [sd getLoginTypeForDomain: _domain];
if(type != nil && [type isEqualToString: @"openid"])
{
config = [sd getLoginConfigForDomain: _domain];
[self initializeWithConfig: config];
}
else
{
[self errorWithFormat: @"Missing parameters from sogo.conf"];
}
}
else if ([[self class] checkUserConfig])
{
openIdConfigUrl = [sd openIdConfigUrl];
openIdScope = [sd openIdScope];
openIdClient = [sd openIdClient];
openIdClientSecret = [sd openIdClientSecret];
openIdEmailParam = [sd openIdEmailParam];
openIdEnableRefreshToken = [sd openIdEnableRefreshToken];
userTokenInterval = [sd openIdTokenCheckInterval];
forDomain = _domain;
[self _loadSessionFromCache: _domain];
if(cacheUpdateNeeded)
{
[self fecthConfiguration: _domain];
}
}
else
{
[self errorWithFormat: @"Missing parameters from sogo.conf"];
}
}
- (NSString *) _get_user_domain
{
SOGoUser* user = [[context activeUser] login];
NSLog(@"user is %@", user);
}
- (WOResponse *) _performOpenIdRequest: (NSString *) endpoint
method: (NSString *) method
headers: (NSDictionary *) headers
body: (NSData *) body
{
NSURL *url;
NSUInteger status;
WORequest *request;
WOResponse *response;
WOHTTPConnection *httpConnection;
[self _get_user_domain];
url = [NSURL URLWithString: endpoint];
if (url)
{
if(SOGoOpenIDDebugEnabled)
{
NSLog(@"OpenId perform request: %@ %@", method, endpoint);
NSLog(@"OpenId perform request, headers %@", headers);
if(body)
NSLog(@"OpenId perform request: content %@", [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]);
}
httpConnection = [[WOHTTPConnection alloc] initWithURL: url];
[httpConnection autorelease];
request = [[WORequest alloc] initWithMethod: method
uri: [endpoint hostlessURL]
httpVersion: @"HTTP/1.1"
headers: headers content: body
userInfo: nil];
[request autorelease];
[httpConnection sendRequest: request];
response = [httpConnection readResponse];
status = [response status];
if(status >= 200 && status <500 && status != 404)
return response;
else if (status == 404)
{
[self errorWithFormat: @"OpenID endpoint not found (404): %@", endpoint];
return nil;
}
else
{
[self errorWithFormat: @"OpenID server internal error during %@: %@", endpoint, response];
return nil;
}
}
else
{
[self errorWithFormat: @"OpenID can't handle endpoint (not a url): '%@'", endpoint];
return nil;
}
}
- (NSMutableDictionary *) fecthConfiguration: (NSString*) _domain
{
NSString *content;
WOResponse * response;
NSUInteger status;
NSMutableDictionary *result;
NSDictionary *config, *headers;
NSURL *url;
result = [NSMutableDictionary dictionary];
[result setObject: self->openIdConfigUrl forKey: @"url"];
url = [NSURL URLWithString: self->openIdConfigUrl ];
if (url)
{
if(_domain != nil && [_domain length] > 0)
headers = [NSDictionary dictionaryWithObject: _domain forKey: @"sogo-user-domain"];
else
headers = nil;
response = [self _performOpenIdRequest: self->openIdConfigUrl
method: @"GET"
headers: headers
body: nil];
if (response)
{
status = [response status];
if(status >= 200 && status <300)
{
content = [response contentString];
config = [content objectFromJSONString];
self->authorizationEndpoint = [config objectForKey: @"authorization_endpoint"];
self->tokenEndpoint = [config objectForKey: @"token_endpoint"];
self->userinfoEndpoint = [config objectForKey: @"userinfo_endpoint"];
self->endSessionEndpoint = [config objectForKey: @"end_session_endpoint"];
//Optionnals?
if([config objectForKey: @"introspection_endpoint"])
self->introspectionEndpoint = [config objectForKey: @"introspection_endpoint"];
if([config objectForKey: @"revocation_endpoint"])
self->revocationEndpoint = [config objectForKey: @"revocation_endpoint"];
openIdSessionIsOK = YES;
[self _saveSessionToCache: _domain];
}
else
{
[self logWithFormat: @"Error during fetching the configuration (status %d), response: %@", status, response];
}
}
else
[result setObject: @"http-error" forKey: @"error"];
}
else
[result setObject: @"invalid-url" forKey: @"error"];
return result;
}
+ (SOGoOpenIdSession *) OpenIdSession: (NSString *) _domain
{
SOGoOpenIdSession *newSession;
newSession = [self new];
[newSession autorelease];
[newSession initialize: _domain];
return newSession;
}
+ (SOGoOpenIdSession *) OpenIdSessionWithConfig: (NSDictionary *) _config
{
SOGoOpenIdSession *newSession;
newSession = [self new];
[newSession autorelease];
[newSession initializeWithConfig: _config];
return newSession;
}
+ (SOGoOpenIdSession *) OpenIdSessionWithToken: (NSString *) token domain: (NSString *) _domain
{
SOGoOpenIdSession *newSession;
if (token)
{
newSession = [self new];
[newSession autorelease];
[newSession initialize: _domain];
[newSession setAccessToken: token];
}
else
newSession = nil;
return newSession;
}
+ (SOGoOpenIdSession *) OpenIdSessionWithTokenAndConfig: (NSString *) token config: (NSDictionary *) _config
{
SOGoOpenIdSession *newSession;
if (token)
{
newSession = [self new];
[newSession autorelease];
[newSession initializeWithConfig: _config];
[newSession setAccessToken: token];
}
else
newSession = nil;
return newSession;
}
- (BOOL) sessionIsOk
{
return self->openIdSessionIsOK;
}
- (void) _loadSessionFromCache: (NSString*) _domain
{
SOGoCache *cache;
NSString *jsonSession, *cacheKey;
NSDictionary *sessionDict;
if(_domain != nil && [_domain length] > 0)
cacheKey = [self->openIdConfigUrl stringByAppendingFormat: @":%@", _domain];
else
cacheKey = self->openIdConfigUrl;
cache = [SOGoCache sharedCache];
jsonSession = [cache openIdSessionFromServer: cacheKey];
if ([jsonSession length])
{
sessionDict = [jsonSession objectFromJSONString];
ASSIGN (authorizationEndpoint, [sessionDict objectForKey: @"authorization_endpoint"]);
ASSIGN (tokenEndpoint, [sessionDict objectForKey: @"token_endpoint"]);
ASSIGN (userinfoEndpoint, [sessionDict objectForKey: @"userinfo_endpoint"]);
ASSIGN (endSessionEndpoint, [sessionDict objectForKey: @"end_session_endpoint"]);
//Optionnals?
if([sessionDict objectForKey: @"introspection_endpoint"])
ASSIGN (introspectionEndpoint, [sessionDict objectForKey: @"introspection_endpoint"]);
if([sessionDict objectForKey: @"revocation_endpoint"])
ASSIGN (revocationEndpoint, [sessionDict objectForKey: @"revocation_endpoint"]);
openIdSessionIsOK = YES;
}
else
cacheUpdateNeeded = YES;
}
- (void) _saveSessionToCache: (NSString*) _domain
{
SOGoCache *cache;
NSString *jsonSession, *cacheKey;
NSMutableDictionary *sessionDict;
cache = [SOGoCache sharedCache];
sessionDict = [NSMutableDictionary dictionary];
[sessionDict setObject: authorizationEndpoint forKey: @"authorization_endpoint"];
[sessionDict setObject: tokenEndpoint forKey: @"token_endpoint"];
[sessionDict setObject: userinfoEndpoint forKey: @"userinfo_endpoint"];
[sessionDict setObject: endSessionEndpoint forKey: @"end_session_endpoint"];
//Optionnals?
if(introspectionEndpoint)
[sessionDict setObject: introspectionEndpoint forKey: @"introspection_endpoint"];
if(revocationEndpoint)
[sessionDict setObject: revocationEndpoint forKey: @"revocation_endpoint"];
jsonSession = [sessionDict jsonRepresentation];
if(_domain != nil && [_domain length] > 0)
cacheKey = [self->openIdConfigUrl stringByAppendingFormat: @":%@", _domain];
else
cacheKey = self->openIdConfigUrl;
[cache setOpenIdSession: jsonSession
forServer: cacheKey];
}
- (BOOL) _loadUserFromCache: (NSString *) email
{
/*
Return NO if the user token must be check again, YES the user is valid for now
*/
SOGoCache *cache;
NSString *identifier, *nextCheck;
NSTimeInterval nextCheckTime, timeNow;
identifier = [self->openIdClient stringByAppendingString: email];
cache = [SOGoCache sharedCache];
nextCheck = [cache userOpendIdSessionFromServer: identifier];
if ([nextCheck length])
{
timeNow = [[NSDate date] timeIntervalSince1970];
nextCheckTime = [nextCheck doubleValue];
if(timeNow > nextCheckTime)
return NO;
else
return YES;
}
else
return NO;
}
- (void) _saveUserToCache: (NSString *) email
{
SOGoCache *cache;
NSString *identifier, *nextCheck;
NSTimeInterval nextCheckTime;
identifier = [self->openIdClient stringByAppendingString: email];
nextCheckTime = [[NSDate date] timeIntervalSince1970] + self->userTokenInterval;
nextCheck = [NSString stringWithFormat:@"%f", nextCheckTime];
cache = [SOGoCache sharedCache];
[cache setUserOpendIdSessionFromServer: identifier
nextCheckAfter: nextCheck];
}
- (NSString*) loginUrl: (NSString *) oldLocation
{
NSString* logUrl;
logUrl = [self->authorizationEndpoint stringByAppendingFormat: @"?scope=%@", self->openIdScope];
logUrl = [logUrl stringByAppendingString: @"&response_type=code"];
logUrl = [logUrl stringByAppendingFormat: @"&client_id=%@", self->openIdClient];
logUrl = [logUrl stringByAppendingFormat: @"&redirect_uri=%@", oldLocation];
if(self->forDomain != nil && [self->forDomain length] > 0)
logUrl = [logUrl stringByAppendingFormat: @"&sogo_domain=%@", forDomain];
// logurl = [self->logurl stringByAppendingFormat: @"&state=%@", state];
return logUrl;
}
- (NSString *) logoutUrl
{
return self->endSessionEndpoint;
}
- (NSString*) getRefreshToken
{
return self->refreshToken;
}
- (NSString*) getToken
{
return self->accessToken;
}
- (void) setAccessToken: (NSString* ) token
{
self->accessToken = token;
}
- (NSString *) getCurrentToken
{
NSString *currentToken;
//See if the current token has been refreshed
currentToken = [[[GCSFolderManager defaultFolderManager] openIdFolder] getNewToken: self->accessToken];
if(currentToken)
{
//be sure the old token has been cleaned
[[[GCSFolderManager defaultFolderManager] openIdFolder] deleteOpenIdSessionFor: self->accessToken];
return currentToken;
}
return self->accessToken;
}
- (NSMutableDictionary *) fetchToken: (NSString * ) code redirect: (NSString *) oldLocation
{
NSString *location, *form, *content;
WOResponse *response;
NSUInteger status;
NSMutableDictionary *result;
NSDictionary *headers;
NSDictionary *tokenRet;
NSURL *url;
result = [NSMutableDictionary dictionary];
[result setObject: @"ok" forKey: @"error"];
location = self->tokenEndpoint;
url = [NSURL URLWithString: location];
if (url)
{
form = @"grant_type=authorization_code";
form = [form stringByAppendingFormat: @"&code=%@", code];
form = [form stringByAppendingFormat: @"&redirect_uri=%@", [oldLocation stringByEscapingURL]];
form = [form stringByAppendingFormat: @"&client_secret=%@", self->openIdClientSecret];
form = [form stringByAppendingFormat: @"&client_id=%@", self->openIdClient];
if(self->forDomain != nil && [self->forDomain length] > 0)
headers = [NSDictionary dictionaryWithObjectsAndKeys: @"application/x-www-form-urlencoded", @"content-type",
self->forDomain, @"sogo-user-domain", nil];
else
headers = [NSDictionary dictionaryWithObject: @"application/x-www-form-urlencoded" forKey: @"content-type"];
response = [self _performOpenIdRequest: location
method: @"POST"
headers: headers
body: [form dataUsingEncoding:NSUTF8StringEncoding]];
if (response)
{
status = [response status];
if(status >= 200 && status <300)
{
content = [response contentString];
tokenRet = [content objectFromJSONString];
if (SOGoOpenIDDebugEnabled)
{
NSLog(@"fetch token response: %@", tokenRet);
}
self->accessToken = [tokenRet objectForKey: @"access_token"];
self->refreshToken = [tokenRet objectForKey: @"refresh_token"];
self->refreshExpiresIn = [tokenRet objectForKey: @"refresh_expires_in"];
self->idToken = [tokenRet objectForKey: @"id_token"];
self->tokenType = [tokenRet objectForKey: @"token_type"];
self->expiresIn = [tokenRet objectForKey: @"expires_in"];
}
else
{
[self logWithFormat: @"Error during fetching the token (status %d), response: %@", status, response];
}
}
else
{
[result setObject: @"http-error" forKey: @"error"];
}
}
else
[result setObject: @"invalid-url" forKey: @"error"];
return result;
}
- (NSMutableDictionary *) refreshToken: (NSString * ) userRefreshToken
{
NSString *location, *form, *content;
WOResponse *response;
NSUInteger status;
NSMutableDictionary *result;
NSDictionary *headers;
NSDictionary *refreshTokenRet;
NSURL *url;
result = [NSMutableDictionary dictionary];
[result setObject: @"ok" forKey: @"error"];
if(!userRefreshToken || [userRefreshToken length] == 0)
{
[result setObject: @"invalid-token" forKey: @"error"];
return result;
}
location = self->tokenEndpoint;
url = [NSURL URLWithString: location];
if (url)
{
form = @"grant_type=refresh_token";
form = [form stringByAppendingFormat: @"&scope=%@", self->openIdScope];
form = [form stringByAppendingFormat: @"&refresh_token=%@", userRefreshToken];
form = [form stringByAppendingFormat: @"&client_secret=%@", self->openIdClientSecret];
form = [form stringByAppendingFormat: @"&client_id=%@", self->openIdClient];
if(self->forDomain != nil && [self->forDomain length] > 0)
headers = [NSDictionary dictionaryWithObjectsAndKeys: @"application/x-www-form-urlencoded", @"content-type",
self->forDomain, @"sogo-user-domain", nil];
else
headers = [NSDictionary dictionaryWithObject: @"application/x-www-form-urlencoded" forKey: @"content-type"];
response = [self _performOpenIdRequest: location
method: @"POST"
headers: headers
body: [form dataUsingEncoding:NSUTF8StringEncoding]];
if (response)
{
status = [response status];
if(status >= 200 && status <300)
{
content = [response contentString];
refreshTokenRet = [content objectFromJSONString];
if (SOGoOpenIDDebugEnabled)
{
NSLog(@"refresh token response: %@", refreshTokenRet);
}
self->accessToken = [refreshTokenRet objectForKey: @"access_token"];
self->refreshToken = [refreshTokenRet objectForKey: @"refresh_token"];
self->refreshExpiresIn = [refreshTokenRet objectForKey: @"refresh_expires_in"];
self->tokenType = [refreshTokenRet objectForKey: @"token_type"];
self->expiresIn = [refreshTokenRet objectForKey: @"expires_in"];
}
else
{
[self logWithFormat: @"Error during refreshing the token (status %d), response: %@", status, response];
}
}
else
{
[result setObject: @"http-error" forKey: @"error"];
}
}
else
[result setObject: @"invalid-url" forKey: @"error"];
return result;
}
- (NSMutableDictionary *) fetchUserInfo
{
NSString *location, *auth, *content;
WOResponse *response;
NSUInteger status;
NSMutableDictionary *result;
NSDictionary *profile, *headers;
NSURL *url;
NSString *email;
result = [NSMutableDictionary dictionary];
[result setObject: @"ok" forKey: @"error"];
location = self->userinfoEndpoint;
url = [NSURL URLWithString: location];
if (url)
{
auth = [NSString stringWithFormat: @"Bearer %@", self->accessToken];
if(self->forDomain != nil && [self->forDomain length] > 0)
headers = [NSDictionary dictionaryWithObjectsAndKeys: @"application/x-www-form-urlencoded", @"content-type",
self->forDomain, @"sogo-user-domain",
auth, @"authorization", nil];
else
headers = [NSDictionary dictionaryWithObject: auth forKey: @"authorization"];
response = [self _performOpenIdRequest: location
method: @"GET"
headers: headers
body: nil];
if (response)
{
status = [response status];
if(status >= 200 && status <300)
{
content = [response contentString];
profile = [content objectFromJSONString];
if(SOGoOpenIDDebugEnabled && profile)
NSLog(@"OpenId fetch user info, profile is %@", profile);
/*profile = {"sub":"70a3e6a1-37cf-4cf6-b114-6973aabca86a",
"email_verified":false,
"address":{},
"name":"Foo Bar",
"preferred_username":"myuser",
"given_name":"Foo",
"family_name":"Bar",
"email":"myuser@user.com"}*/
if (email = [profile objectForKey: self->openIdEmailParam])
{
if(self->userTokenInterval > 0)
[self _saveUserToCache: email];
[result setObject: email forKey: @"login"];
}
else
[result setObject: @"no mail found" forKey: @"error"];
}
else
{
[self logWithFormat: @"Error during fetching the token (status %d), response: %@", status, response];
[result setObject: @"http-error" forKey: @"error"];
}
}
else
{
[result setObject: @"http-error" forKey: @"error"];
}
}
else
[result setObject: @"invalid-url" forKey: @"error"];
return result;
}
+ (void) deleteValueForSessionKey: (NSString *) theSessionKey
{
GCSOpenIdFolder *folder;
folder = [[GCSFolderManager defaultFolderManager] openIdFolder];
[folder deleteOpenIdSessionFor: theSessionKey];
}
- (NSString *) _login
{
NSMutableDictionary *resultUserInfo, *resultResfreh;
NSString* _oldAccessToken;
resultUserInfo = [self fetchUserInfo];
if ([[resultUserInfo objectForKey: @"error"] isEqualToString: @"ok"])
{
//Save some infos as the refresh token to the database
[[[GCSFolderManager defaultFolderManager] openIdFolder] writeOpenIdSession: self->accessToken
withOldSession: nil
withRefreshToken: self->refreshToken
withExpire: self->expiresIn
withRefreshExpire: self->refreshExpiresIn];
return [resultUserInfo objectForKey: @"login"];
}
else if(openIdEnableRefreshToken)
{
//try to refresh
if(self->accessToken)
{
self->refreshToken = [[[GCSFolderManager defaultFolderManager] openIdFolder] getRefreshToken: self->accessToken];
//remove old session
[[[GCSFolderManager defaultFolderManager] openIdFolder] deleteOpenIdSessionFor: self->accessToken];
}
if(self->refreshToken)
{
_oldAccessToken = self->accessToken;
resultResfreh = [self refreshToken: self->refreshToken];
if ([[resultResfreh objectForKey: @"error"] isEqualToString: @"ok"])
{
resultUserInfo = [self fetchUserInfo];
if ([[resultUserInfo objectForKey: @"error"] isEqualToString: @"ok"])
{
[[[GCSFolderManager defaultFolderManager] openIdFolder] writeOpenIdSession: self->accessToken
withOldSession: _oldAccessToken
withRefreshToken: self->refreshToken
withExpire: self->expiresIn
withRefreshExpire: self->refreshExpiresIn];
return [resultUserInfo objectForKey: @"login"];
}
}
}
//The acces token hasn't work, delete the session in database if needed
if(self->accessToken)
{
[[[GCSFolderManager defaultFolderManager] openIdFolder] deleteOpenIdSessionFor: self->accessToken];
}
[self errorWithFormat: @"Can't get user email from profile because: %@", [resultUserInfo objectForKey: @"error"]];
}
else
{
//remove old session
[[[GCSFolderManager defaultFolderManager] openIdFolder] deleteOpenIdSessionFor: self->accessToken];
}
return @"anonymous";
}
- (NSString *) login: (NSString *) email
{
//Check if we need to fetch userinfo
if(self->userTokenInterval > 0 && [self _loadUserFromCache: email])
{
return email;
}
else
{
return [self _login];
}
}
@end
+4 -12
View File
@@ -247,20 +247,12 @@
usingKey: theKey];
r = [decodedValue rangeOfString: @":"];
if (r.location != NSNotFound)
{
*theLogin = [decodedValue substringToIndex: r.location];
*thePassword = [decodedValue substringFromIndex: r.location+1];
}
else
{
*theLogin = nil;
*thePassword = nil;
}
*theLogin = [decodedValue substringToIndex: r.location];
*thePassword = [decodedValue substringFromIndex: r.location+1];
*theDomain = nil;
sd = [SOGoSystemDefaults sharedSystemDefaults];
if (*theLogin &&[sd enableDomainBasedUID])
if ([sd enableDomainBasedUID])
{
r = [*theLogin rangeOfString: @"@" options: NSBackwardsSearch];
if (r.location != NSNotFound)
+1 -18
View File
@@ -28,7 +28,6 @@
#import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoDomainDefaults.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoTextTemplateFile.h>
@@ -698,11 +697,8 @@ static NSString *sieveScriptName = @"sogo";
NSDictionary *result;
NSString *login, *authname, *password;
SOGoDomainDefaults *dd;
SOGoSystemDefaults *sd;
NGSieveClient *client;
NSString *sieveServer, *sieveScheme, *sieveQuery, *imapServer;
NSString *imapAuthMech, *userDomain;
NSRange r;
NSURL *url, *cUrl;
int sievePort;
BOOL connected;
@@ -777,20 +773,7 @@ static NSString *sieveScriptName = @"sogo";
url = [NSURL URLWithString: [NSString stringWithFormat: @"%@://%@:%d%@",
sieveScheme, sieveServer, sievePort, sieveQuery]];
//In case of differrent auth method for different domain, check it
sd = [SOGoSystemDefaults sharedSystemDefaults];
imapAuthMech = nil;
if([sd doesLoginTypeByDomain])
{
r = [theUsername rangeOfString: @"@"];
if (r.location != NSNotFound)
{
userDomain = [theUsername substringFromIndex: r.location+1];
imapAuthMech = [sd getImapAuthMechForDomain: userDomain];
}
}
client = [[NGSieveClient alloc] initWithURL: url andAuthMech: imapAuthMech];
client = [[NGSieveClient alloc] initWithURL: url];
if (!client) {
[self errorWithFormat: @"Sieve connection failed on %@", [url description]];
-18
View File
@@ -36,11 +36,6 @@ static const NSString *kDisableSharingCalendar = @"Calendar";
+ (SOGoSystemDefaults *) sharedSystemDefaults;
- (NSArray *) domainIds;
- (BOOL) doesLoginTypeByDomain;
- (NSString *) getLoginTypeForDomain: (NSString*) _domain;
- (NSString *) getLoginConfigForDomain: (NSDictionary*) _domain;
- (NSString *) getImapAuthMechForDomain: (NSString*) _domain;
- (NSString *) getSmtpAuthMechForDomain: (NSString*) _domain;
- (BOOL) forbidUnknownDomainsAuth;
- (NSArray *) domainsAllowed;
- (BOOL) enableDomainBasedUID;
@@ -81,7 +76,6 @@ static const NSString *kDisableSharingCalendar = @"Calendar";
- (BOOL) uixDebugEnabled;
- (BOOL) easDebugEnabled;
- (BOOL) openIdDebugEnabled;
- (BOOL) tnefDecoderDebugEnabled;
- (BOOL) xsrfValidationEnabled;
@@ -94,21 +88,11 @@ NSComparisonResult languageSort(id el1, id el2, void *context);
- (NSString *) loginSuffix;
- (NSString *) authenticationType;
- (BOOL) isSsoUsed: (NSString *) domain;
- (NSString *) davAuthenticationType;
- (NSString *) CASServiceURL;
- (BOOL) CASLogoutEnabled;
- (NSString *) openIdConfigUrl;
- (NSString *) openIdScope;
- (NSString *) openIdClient;
- (NSString *) openIdClientSecret;
- (NSString *) openIdEmailParam;
- (BOOL) openIdEnableRefreshToken;
- (BOOL) openIdLogoutEnabled: (NSString *) _domain;
- (int) openIdTokenCheckInterval;
- (NSString *) SAML2PrivateKeyLocation;
- (NSString *) SAML2CertificateLocation;
- (NSString *) SAML2IdpMetadataLocation;
@@ -156,8 +140,6 @@ NSComparisonResult languageSort(id el1, id el2, void *context);
- (BOOL)isURLEncryptionEnabled;
- (NSString *)urlEncryptionPassphrase;
- (NSString *)urlCreateAccount;
@end
#endif /* SOGOSYSTEMDEFAULTS_H */
-224
View File
@@ -262,143 +262,6 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict,
return [domains allKeys];
}
- (BOOL) doesLoginTypeByDomain
{
return ([self dictionaryForKey: @"SOGoLoginTypeByDomain"] != nil);
}
- (NSString *) getLoginTypeForDomain: (NSString*) _domain
{
NSDictionary *domains, *config;
NSString *type;
if(![self doesLoginTypeByDomain])
return nil;
domains = [self dictionaryForKey: @"SOGoLoginTypeByDomain"];
if([domains objectForKey: _domain])
{
config = [domains objectForKey: _domain];
}
else if([domains objectForKey: @"login_default"])
{
config = [domains objectForKey: @"login_default"];
}
else
return nil;
if((type = [config objectForKey: @"type"]))
{
return type;
}
else
return nil;
}
- (NSString *) getImapAuthMechForDomain: (NSString*) _domain
{
NSDictionary *domains, *config;
NSString *type;
if(![self doesLoginTypeByDomain])
return nil;
domains = [self dictionaryForKey: @"SOGoLoginTypeByDomain"];
if([domains objectForKey: _domain])
{
config = [domains objectForKey: _domain];
}
else if([domains objectForKey: @"login_default"])
{
config = [domains objectForKey: @"login_default"];
}
else
return nil;
if((type = [config objectForKey: @"imapAuthMech"]))
{
return type;
}
else
return nil;
}
- (NSString *) getSmtpAuthMechForDomain: (NSString*) _domain
{
NSDictionary *domains, *config;
NSString *type;
if(![self doesLoginTypeByDomain])
return nil;
domains = [self dictionaryForKey: @"SOGoLoginTypeByDomain"];
if([domains objectForKey: _domain])
{
config = [domains objectForKey: _domain];
}
else if([domains objectForKey: @"login_default"])
{
config = [domains objectForKey: @"login_default"];
}
else
return nil;
if((type = [config objectForKey: @"smtpAuthMech"]))
{
return type;
}
else
return nil;
}
- (NSString *) getLoginConfigForDomain: (NSDictionary*) _domain
{
NSDictionary *domains, *config;
if(![self doesLoginTypeByDomain])
return nil;
domains = [self dictionaryForKey: @"SOGoLoginTypeByDomain"];
if([domains objectForKey: _domain])
{
config = [domains objectForKey: _domain];
}
else if([domains objectForKey: @"login_default"])
{
config = [domains objectForKey: @"login_default"];
}
if(config)
return config;
else
return nil;
}
- (BOOL) hasOpenIdType
{
if([self doesLoginTypeByDomain])
{
NSDictionary *domainsConfig;
NSEnumerator *e;
NSString *domain, *type;
if(![self doesLoginTypeByDomain])
return NO;
domainsConfig = [self dictionaryForKey: @"SOGoLoginTypeByDomain"];
e = [domainsConfig keyEnumerator];
while((domain = [e nextObject]))
{
if((type = [[domainsConfig objectForKey: domain] objectForKey: @"type"]))
{
if([type isEqualToString: @"openid"])
return YES;
}
}
return NO;
}
else
return [[self authenticationType] isEqualToString: @"openid"];
}
- (BOOL) enableDomainBasedUID
{
return [self boolForKey: @"SOGoEnableDomainBasedUID"];
@@ -644,11 +507,6 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict,
return [self boolForKey: @"SOGoEASDebugEnabled"];
}
- (BOOL) openIdDebugEnabled
{
return [self boolForKey: @"SOGoOpenIDDebugEnabled"];
}
- (BOOL) tnefDecoderDebugEnabled
{
return [self boolForKey: @"SOGoTnefDecoderDebugEnabled"];
@@ -719,16 +577,6 @@ NSComparisonResult languageSort(id el1, id el2, void *context)
return [[self stringForKey: @"SOGoAuthenticationType"] lowercaseString];
}
- (BOOL) isSsoUsed: (NSString *) domain
{
NSString* authType;
authType = [self getLoginTypeForDomain: domain];
if(!authType)
authType = [self authenticationType];
return ([authType isEqualToString: @"cas"] || [authType isEqualToString: @"saml2"] || [authType isEqualToString: @"openid"]);
}
- (NSString *) davAuthenticationType
{
return [[self stringForKey: @"SOGoDAVAuthenticationType"] lowercaseString];
@@ -744,73 +592,6 @@ NSComparisonResult languageSort(id el1, id el2, void *context)
return [self boolForKey: @"SOGoCASLogoutEnabled"];
}
/* OpenId Support */
- (NSString *) openIdConfigUrl
{
return [self stringForKey: @"SOGoOpenIdConfigUrl"];
}
- (NSString *) openIdScope
{
return [self stringForKey: @"SOGoOpenIdScope"];
}
- (NSString *) openIdClient
{
return [self stringForKey: @"SOGoOpenIdClient"];
}
- (NSString *) openIdClientSecret
{
return [self stringForKey: @"SOGoOpenIdClientSecret"];
}
- (NSString *) openIdEmailParam
{
NSString *emailParam;
emailParam = [self stringForKey: @"SOGoOpenIdEmailParam"];
if(!emailParam)
emailParam = @"email";
return emailParam;
}
- (BOOL) openIdLogoutEnabled: (NSString *) _domain
{
if(_domain && [self doesLoginTypeByDomain])
{
NSDictionary *config;
NSString *type;
id value;
if((config = [self getLoginConfigForDomain: _domain]))
{
if((type = [config objectForKey: @"type"]) && [type isEqualToString:@"openid"])
return [self boolForKey: @"SOGoOpenIdLogoutEnabled" andDict: config];
}
return NO;
}
return [self boolForKey: @"SOGoOpenIdLogoutEnabled"];
}
- (int) openIdTokenCheckInterval
{
int v;
v = [self integerForKey: @"SOGoOpenIdTokenCheckInterval"];
if (!v)
v = 0;
if(v<0)
v = 0;
return v;
}
- (BOOL) openIdEnableRefreshToken
{
return [self boolForKey: @"SOGoOpenIdEnableRefreshToken"];
}
/* SAML2 support */
- (NSString *) SAML2PrivateKeyLocation
{
@@ -1147,9 +928,4 @@ NSComparisonResult languageSort(id el1, id el2, void *context)
return disableExport;
}
- (NSString *)urlCreateAccount
{
return [self stringForKey: @"SOGoURLCreateAccount"];
}
@end
-1
View File
@@ -91,7 +91,6 @@
/* properties */
- (NSString *) domain;
- (NSString *) loginDomain;
- (id <SOGoSource>) authenticationSource;
- (NSArray *) allEmails;
-13
View File
@@ -301,19 +301,6 @@ static const NSString *kEncryptedUserNamePrefix = @"uenc";
return [self _fetchFieldForUser: @"c_domain"];
}
- (NSString *) loginDomain
{
NSRange r;
NSString *domain = nil;
r = [self->login rangeOfString: @"@"];
if (r.location != NSNotFound)
{
domain = [self->login substringFromIndex: r.location+1];
}
return domain;
}
- (id <SOGoSource>) authenticationSource
{
NSString *sourceID;
-1
View File
@@ -587,7 +587,6 @@ static const NSString *kObfuscatedSecondaryEmailKey = @"obfuscatedSecondaryEmail
sd = [SOGoSystemDefaults sharedSystemDefaults];
username = _login;
NSLog(@"D login are %@", _login);
if (*_domain && ![*_domain isKindOfClass: NSNullK])
{
-2
View File
@@ -56,8 +56,6 @@
andPassword: (NSString *) password
inContext: (WOContext *) context;
- (NSArray *)getCookiesIfNeeded: (WOContext *)_ctx;
@end
#endif /* _SOGOWEBAUTHENTICATOR_H_ */
+14 -122
View File
@@ -35,7 +35,6 @@
#import "SOGoCache.h"
#import "SOGoCASSession.h"
#import "SOGoOpenIdSession.h"
#import "SOGoPermissions.h"
#import "SOGoSession.h"
#import "SOGoSystemDefaults.h"
@@ -130,56 +129,22 @@
grace: (int *) _grace
useCache: (BOOL) _useCache
{
SOGoCASSession *casSession;
SOGoOpenIdSession * openIdSession;
SOGoCASSession *session;
SOGoSystemDefaults *sd;
NSString *authenticationType;
NSString* loginDomain;
BOOL rc;
sd = [SOGoSystemDefaults sharedSystemDefaults];
NSLog(@"B Credentials are %@", _login);
//Basic check
if(!_login)
return NO;
if(_login && [_login length] == 0)
return NO;
loginDomain = nil;
if(*_domain == nil || [*_domain length] == 0)
{
NSRange r;
r = [_login rangeOfString: @"@"];
if (r.location != NSNotFound)
{
loginDomain = [_login substringFromIndex: r.location+1];
}
}
if(loginDomain)
NSLog(@"C domain are %@", loginDomain);
if([sd doesLoginTypeByDomain])
authenticationType = [sd getLoginTypeForDomain: loginDomain];
else
authenticationType = [sd authenticationType];
authenticationType = [sd authenticationType];
if ([authenticationType isEqualToString: @"cas"])
{
casSession = [SOGoCASSession CASSessionWithIdentifier: _pwd fromProxy: NO];
if (casSession)
rc = [[casSession login] isEqualToString: _login];
session = [SOGoCASSession CASSessionWithIdentifier: _pwd fromProxy: NO];
if (session)
rc = [[session login] isEqualToString: _login];
else
rc = NO;
}
else if ([authenticationType isEqualToString: @"openid"])
{
openIdSession = [SOGoOpenIdSession OpenIdSessionWithToken: _pwd domain: loginDomain];
if (openIdSession)
rc = [[openIdSession login: _login] isEqualToString: _login];
else
rc = NO;
}
#if defined(SAML2_CONFIG)
else if ([authenticationType isEqualToString: @"saml2"])
{
@@ -198,8 +163,9 @@
domain: _domain
perr: _perr
expire: _expire
grace: _grace
grace: _grace
useCache: _useCache];
//[self logWithFormat: @"Checked login with ppolicy enabled: %d %d %d", *_perr, *_expire, *_grace];
// It's important to return the real value here. The callee will handle
@@ -273,15 +239,12 @@
sessionKey = [creds objectAtIndex:1];
NSLog(@"AAAA decodevalue for");
[SOGoSession decodeValue: [SOGoSession valueForSessionKey: sessionKey]
usingKey: userKey
login: &login
domain: &domain
password: &pwd];
NSLog(@"A Credentials are %@", login);
if (![self checkLogin: login
password: pwd
domain: &domain
@@ -303,42 +266,32 @@
{
NSString *authType, *password;
SOGoSystemDefaults *sd;
SOGoUser *user;
NSRange r;
NSString *loginDomain, *login;
password = [self passwordInContext: context];
if ([password length])
{
user = [self userInContext: context];
login = [user loginInDomain];
r = [login rangeOfString: @"@"];
if (r.location != NSNotFound)
loginDomain = [login substringFromIndex: r.location+1];
else
loginDomain = nil;
sd = [SOGoSystemDefaults sharedSystemDefaults];
if([sd doesLoginTypeByDomain])
authType = [sd getLoginTypeForDomain: loginDomain];
else
authType = [sd authenticationType];
authType = [sd authenticationType];
if ([authType isEqualToString: @"cas"])
{
SOGoCASSession *session;
SOGoUser *user;
NSString *service, *scheme;
session = [SOGoCASSession CASSessionWithIdentifier: password
fromProxy: NO];
user = [self userInContext: context];
// Try configured CAS service name first
service = [[user domainDefaults] imapCASServiceName];
if (!service)
{
// We must NOT assume the scheme exists
scheme = [server scheme];
if (!scheme)
scheme = @"imap";
service = [NSString stringWithFormat: @"%@://%@",
scheme, [server host]];
}
@@ -347,18 +300,10 @@
[session invalidateTicketForService: service];
password = [session ticketForService: service];
if ([password length] || renew)
[session updateCache];
}
else if ([authType isEqualToString: @"openid"])
{
SOGoOpenIdSession* session;
//If the token has been refresh during the request, we need to use the new access_token
//as the one from the cookie is no more valid
session = [SOGoOpenIdSession OpenIdSessionWithToken: password domain: loginDomain];
password = [session getCurrentToken];
}
#if defined(SAML2_CONFIG)
else if ([authType isEqualToString: @"saml2"])
{
@@ -485,57 +430,4 @@
return authCookie;
}
- (NSArray *) getCookiesIfNeeded: (WOContext *)_ctx
{
NSArray *listCookies = nil;
SOGoSystemDefaults *sd;
NSString *authType, *username, *login, *loginDomain;
NSRange r;
SOGoUser *user;
user = [self userInContext: _ctx];
login = [user loginDomain];
r = [login rangeOfString: @"@"];
if (r.location != NSNotFound)
loginDomain = [login substringFromIndex: r.location+1];
else
loginDomain = nil;
sd = [SOGoSystemDefaults sharedSystemDefaults];
if(loginDomain && [sd doesLoginTypeByDomain])
authType = [sd getLoginTypeForDomain: loginDomain];
else
authType = [sd authenticationType];
if([authType isEqualToString:@"openid"] && [sd openIdEnableRefreshToken])
{
NSString *currentPassword, *newPassword;
SOGoOpenIdSession *openIdSession;
WOCookie* newCookie;
currentPassword = [self passwordInContext: _ctx];
newPassword = [self imapPasswordInContext: _ctx forURL: nil forceRenew: NO];
if(currentPassword && newPassword && ![newPassword isEqualToString: currentPassword])
{
openIdSession = [SOGoOpenIdSession OpenIdSessionWithToken: newPassword domain: loginDomain];
if (openIdSession)
username = [openIdSession login: @""]; //Force to refresh the name
else
username = [[self userInContext: _ctx] login];
newCookie = [self cookieWithUsername: username
andPassword: newPassword
inContext: _ctx];
listCookies = [[NSArray alloc] initWithObjects: newCookie, nil];
[listCookies autorelease];
}
if(listCookies && [listCookies isKindOfClass:[NSArray class]] && [listCookies count] > 0)
return listCookies;
else
return nil;
}
else
return nil;
}
@end /* SOGoWebAuthenticator */
-4
View File
@@ -267,8 +267,4 @@
return ret;
}
- (NSString *) applicationName {
return @"SOGo";
}
@end
-235
View File
@@ -1,235 +0,0 @@
/* SOGoToolExpireUserSessions.m - this file is part of SOGo
*
* Copyright (C) 2012-2021 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSUserDefaults.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLContentStore/GCSChannelManager.h>
#import <GDLContentStore/NSURL+GCS.h>
#import <NGExtensions/NSNull+misc.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoSession.h>
#import <SOGo/SOGoOpenIdSession.h>
#import "SOGoTool.h"
@interface SOGoToolExpireUserSessions : SOGoTool
@end
@implementation SOGoToolExpireUserSessions
+ (NSString *) command
{
return @"expire-sessions";
}
+ (NSString *) description
{
return @"expires user sessions without activity for specified number of minutes";
}
- (void) usage
{
fprintf (stderr, "expire-sessions [nbMinutes]\n\n"
" nbMinutes Number of minutes of inactivity after which a user session will be expired\n"
"\n"
"The expire-sessions action should be configured as a cronjob.\n");
}
- (BOOL) expireUserOpenIdSessionOlderThan: (int) nbMinutes
{
BOOL rc;
EOAdaptorChannel *channel;
GCSChannelManager *cm;
NSArray *attrs;
NSDictionary *qresult;
NSException *ex;
NSString *sql, *sessionsFolderURL, *sessionID;
NSURL *tableURL;
NSUserDefaults *ud;
unsigned int now, oldest;
rc = YES;
ud = [NSUserDefaults standardUserDefaults];
now = [[NSCalendarDate calendarDate] timeIntervalSince1970];
oldest = now - (nbMinutes * 60);
sessionID = nil;
sessionsFolderURL = [ud stringForKey: @"OCSOpenIdURL"];
if (!sessionsFolderURL)
{
if (verbose)
NSLog(@"Couldn't read OCSOpenIdURL");
return rc = NO;
}
tableURL = [[NSURL alloc] initWithString: sessionsFolderURL];
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: tableURL];
if (!channel)
{
/* FIXME: nice error msg */
NSLog(@"Can't aquire channel");
return rc = NO;
}
sql = [NSString stringWithFormat: @"SELECT c_user_session FROM %@ WHERE c_access_token_expires_in <= %d",
[tableURL gcsTableName], oldest];
ex = [channel evaluateExpressionX: sql];
if (ex)
{
NSLog(@"%@", [ex reason]);
[ex raise];
return rc = NO;
}
attrs = [channel describeResults: NO];
while ((qresult = [channel fetchAttributes: attrs withZone: NULL]))
{
sessionID = [qresult objectForKey: @"c_user_session"];
if (sessionID)
{
if (verbose)
NSLog(@"Removing session %@", sessionID);
[SOGoOpenIdSession deleteValueForSessionKey: sessionID];
}
}
[cm releaseChannel: channel immediately: YES];
if (verbose && sessionID == nil)
NSLog(@"No session to remove on openId");
return rc;
}
- (BOOL) expireUserSessionOlderThan: (int) nbMinutes
{
BOOL rc;
EOAdaptorChannel *channel;
GCSChannelManager *cm;
NSArray *attrs;
NSDictionary *qresult;
NSException *ex;
NSString *sql, *sessionsFolderURL, *sessionID, *authType;
NSURL *tableURL;
NSUserDefaults *ud;
unsigned int now, oldest;
rc = YES;
ud = [NSUserDefaults standardUserDefaults];
now = [[NSCalendarDate calendarDate] timeIntervalSince1970];
oldest = now - (nbMinutes * 60);
sessionID = nil;
sessionsFolderURL = [ud stringForKey: @"OCSSessionsFolderURL"];
if (!sessionsFolderURL)
{
if (verbose)
NSLog(@"Couldn't read OCSSessionsFolderURL");
return rc = NO;
}
tableURL = [[NSURL alloc] initWithString: sessionsFolderURL];
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: tableURL];
if (!channel)
{
/* FIXME: nice error msg */
NSLog(@"Can't aquire channel");
return rc = NO;
}
sql = [NSString stringWithFormat: @"SELECT c_id FROM %@ WHERE c_lastseen <= %d",
[tableURL gcsTableName], oldest];
ex = [channel evaluateExpressionX: sql];
if (ex)
{
NSLog(@"%@", [ex reason]);
[ex raise];
return rc = NO;
}
attrs = [channel describeResults: NO];
while ((qresult = [channel fetchAttributes: attrs withZone: NULL]))
{
sessionID = [qresult objectForKey: @"c_id"];
if (sessionID)
{
if (verbose)
NSLog(@"Removing session %@", sessionID);
[SOGoSession deleteValueForSessionKey: sessionID];
}
}
[cm releaseChannel: channel immediately: YES];
if (verbose && sessionID == nil)
NSLog(@"No session to remove");
//doing openid session if needed
authType = [ud stringForKey:@"SOGoAuthenticationType"];
if([authType isEqualToString: @"openid"])
{
[self expireUserOpenIdSessionOlderThan: nbMinutes];
}
return rc;
}
- (BOOL) run
{
BOOL rc;
int sessionExpireMinutes = -1;
rc = NO;
if ([arguments count])
{
sessionExpireMinutes = [[arguments objectAtIndex: 0] intValue];
}
NSLog(@"Remove all sessions older than %d min", sessionExpireMinutes);
if (sessionExpireMinutes == 0 && ![[arguments objectAtIndex: 0] isEqualToString:@"0"])
{
//If the input is not a number intValue return 0 so we check that's really the case
[self usage];
}
else if (sessionExpireMinutes >= 0)
{
rc = [self expireUserSessionOlderThan: sessionExpireMinutes];
}
else
{
[self usage];
}
return rc;
}
@end
+1 -76
View File
@@ -33,7 +33,6 @@
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoSession.h>
#import <SOGo/SOGoOpenIdSession.h>
#import "SOGoTool.h"
@@ -60,73 +59,6 @@
"The expire-sessions action should be configured as a cronjob.\n");
}
- (BOOL) expireUserOpenIdSessionOlderThan: (int) nbMinutes
{
BOOL rc;
EOAdaptorChannel *channel;
GCSChannelManager *cm;
NSArray *attrs;
NSDictionary *qresult;
NSException *ex;
NSString *sql, *sessionsFolderURL, *sessionID;
NSURL *tableURL;
NSUserDefaults *ud;
unsigned int now, oldest;
rc = YES;
ud = [NSUserDefaults standardUserDefaults];
now = [[NSCalendarDate calendarDate] timeIntervalSince1970];
oldest = now - (nbMinutes * 60);
sessionID = nil;
sessionsFolderURL = [ud stringForKey: @"OCSOpenIdURL"];
if (!sessionsFolderURL)
{
if (verbose)
NSLog(@"Couldn't read OCSOpenIdURL");
return rc = NO;
}
tableURL = [[NSURL alloc] initWithString: sessionsFolderURL];
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: tableURL];
if (!channel)
{
/* FIXME: nice error msg */
NSLog(@"Can't aquire channel");
return rc = NO;
}
sql = [NSString stringWithFormat: @"SELECT c_user_session FROM %@ WHERE c_access_token_expires_in <= %d",
[tableURL gcsTableName], oldest];
ex = [channel evaluateExpressionX: sql];
if (ex)
{
NSLog(@"%@", [ex reason]);
[ex raise];
return rc = NO;
}
attrs = [channel describeResults: NO];
while ((qresult = [channel fetchAttributes: attrs withZone: NULL]))
{
sessionID = [qresult objectForKey: @"c_user_session"];
if (sessionID)
{
if (verbose)
NSLog(@"Removing session %@", sessionID);
[SOGoOpenIdSession deleteValueForSessionKey: sessionID];
}
}
[cm releaseChannel: channel immediately: YES];
if (verbose && sessionID == nil)
NSLog(@"No session to remove on openId");
return rc;
}
- (BOOL) expireUserSessionOlderThan: (int) nbMinutes
{
BOOL rc;
@@ -135,7 +67,7 @@
NSArray *attrs;
NSDictionary *qresult;
NSException *ex;
NSString *sql, *sessionsFolderURL, *sessionID, *authType;
NSString *sql, *sessionsFolderURL, *sessionID;
NSURL *tableURL;
NSUserDefaults *ud;
@@ -191,13 +123,6 @@
if (verbose && sessionID == nil)
NSLog(@"No session to remove");
//doing openid session if needed
authType = [ud stringForKey:@"SOGoAuthenticationType"];
if([authType isEqualToString: @"openid"])
{
[self expireUserOpenIdSessionOlderThan: nbMinutes];
}
return rc;
}
+7 -23
View File
@@ -488,14 +488,13 @@
&& [user isSuperUser]);
}
- (BOOL) usesOpenIdAuthentication
- (BOOL) usesCASAuthentication
{
SOGoSystemDefaults *sd;
sd = [SOGoSystemDefaults sharedSystemDefaults];
return [[sd authenticationType] isEqualToString: @"openid"];
return [[sd authenticationType] isEqualToString: @"cas"];
}
- (BOOL) usesSAML2Authenticationx
@@ -538,34 +537,19 @@
BOOL canLogoff;
id auth;
SOGoSystemDefaults *sd;
NSString *authType, *login, *loginDomain;
NSRange r;
NSString *authType;
auth = [[self clientObject] authenticatorInContext: context];
if ([auth respondsToSelector: @selector (cookieNameInContext:)])
{
sd = [SOGoSystemDefaults sharedSystemDefaults];
login = [[context activeUser] login];
r = [login rangeOfString: @"@"];
if (r.location != NSNotFound)
loginDomain = [login substringFromIndex: r.location+1];
else
loginDomain = nil;
if(loginDomain && [sd doesLoginTypeByDomain])
authType = [sd getLoginTypeForDomain: loginDomain];
else
authType = [sd authenticationType];
authType = [sd authenticationType];
if ([authType isEqualToString: @"cas"])
canLogoff = [sd CASLogoutEnabled];
canLogoff = [sd CASLogoutEnabled];
else if ([authType isEqualToString: @"saml2"])
canLogoff = [sd SAML2LogoutEnabled];
else if ([authType isEqualToString: @"openid"])
canLogoff = [sd openIdLogoutEnabled: loginDomain];
canLogoff = [sd SAML2LogoutEnabled];
else
canLogoff = [[auth cookieNameInContext: context] length] > 0;
canLogoff = [[auth cookieNameInContext: context] length] > 0;
}
else
canLogoff = NO;
@@ -6,7 +6,6 @@
"Domain" = "Domain";
"Remember username" = "Remember username";
"Connect" = "Connect";
"Create an account" = "Create an account";
/* Appears while authentication is in progress */
"Authenticating" = "Authenticating";
@@ -6,7 +6,6 @@
"Domain" = "Domaine";
"Remember username" = "Se souvenir de moi";
"Connect" = "Connexion";
"Create an account" = "Créer un compte";
/* Appears while authentication is in progress */
"Authenticating" = "Authentification en cours";
+66 -433
View File
@@ -40,7 +40,6 @@
#import <SOGo/SOGoBuild.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoCASSession.h>
#import <SOGo/SOGoOpenIdSession.h>
#if defined(SAML2_CONFIG)
#import <SOGo/SOGoSAML2Session.h>
#endif /* SAML2_ENABLE */
@@ -145,7 +144,6 @@ static const NSString *kJwtKey = @"jwt";
- (WOCookie *) _authLocationCookie: (BOOL) cookieReset
withName: (NSString *) cookieName
withValue: (NSString *) _value
{
WOCookie *locationCookie;
NSString *appName;
@@ -153,10 +151,7 @@ static const NSString *kJwtKey = @"jwt";
NSCalendarDate *date;
rq = [context request];
if(_value)
locationCookie = [WOCookie cookieWithName: cookieName value: _value];
else
locationCookie = [WOCookie cookieWithName: cookieName value: [rq uri]];
locationCookie = [WOCookie cookieWithName: cookieName value: [rq uri]];
appName = [rq applicationName];
[locationCookie setPath: [NSString stringWithFormat: @"/%@/", appName]];
if (cookieReset)
@@ -169,28 +164,6 @@ static const NSString *kJwtKey = @"jwt";
return locationCookie;
}
- (WOCookie *) _domainCookie: (BOOL) cookieReset
withDomain: (NSString *) _domain
{
WOCookie *domainCookie;
NSString *appName;
WORequest *rq;
NSCalendarDate *date;
rq = [context request];
domainCookie = [WOCookie cookieWithName: @"sogo-user-domain" value: _domain];
appName = [rq applicationName];
[domainCookie setPath: [NSString stringWithFormat: @"/%@/", appName]];
if (cookieReset)
{
date = [NSCalendarDate calendarDate];
[date setTimeZone: [NSTimeZone timeZoneForSecondsFromGMT: 0]];
[domainCookie setExpires: [date yesterday]];
}
return domainCookie;
}
//
//
//
@@ -415,7 +388,6 @@ static const NSString *kJwtKey = @"jwt";
return response;
}
- (NSDictionary *) _casRedirectKeys
{
NSDictionary *redirectKeys;
@@ -469,43 +441,42 @@ static const NSString *kJwtKey = @"jwt";
if ([login isEqualToString: @"anonymous"])
login = nil;
if (!login)
{
rq = [context request];
ticket = [rq formValueForKey: @"ticket"];
if ([ticket length])
{
casSession = [SOGoCASSession CASSessionWithTicket: ticket
fromProxy: NO];
login = [casSession login];
if ([login length])
{
auth = [[WOApplication application]
authenticatorInContext: context];
casCookie = [auth cookieWithUsername: login
andPassword: [casSession identifier]
inContext: context];
[casSession updateCache];
newLocation = [rq cookieValueForKey: @"cas-location"];
/* login callback, we expire the "cas-location" cookie, created
below */
casLocationCookie = [self _authLocationCookie: YES
withName: @"cas-location"
withValue: nil];
}
rq = [context request];
ticket = [rq formValueForKey: @"ticket"];
if ([ticket length])
{
casSession = [SOGoCASSession CASSessionWithTicket: ticket
fromProxy: NO];
login = [casSession login];
if ([login length])
{
auth = [[WOApplication application]
authenticatorInContext: context];
casCookie = [auth cookieWithUsername: login
andPassword: [casSession identifier]
inContext: context];
[casSession updateCache];
newLocation = [rq cookieValueForKey: @"cas-location"];
/* login callback, we expire the "cas-location" cookie, created
below */
casLocationCookie = [self _authLocationCookie: YES
withName: @"cas-location"];
}
}
else
{
/* anonymous and no ticket, possibly a logout request from CAS
* See: https://wiki.jasig.org/display/CASUM/Single+Sign+Out
*/
logoutRequest = [rq formValueForKey: @"logoutRequest"];
if ([logoutRequest length])
{
[SOGoCASSession handleLogoutRequest: logoutRequest];
return [self responseWithStatus: 200];
}
}
}
else
{
/* anonymous and no ticket, possibly a logout request from CAS
* See: https://wiki.jasig.org/display/CASUM/Single+Sign+Out
*/
logoutRequest = [rq formValueForKey: @"logoutRequest"];
if ([logoutRequest length])
{
[SOGoCASSession handleLogoutRequest: logoutRequest];
return [self responseWithStatus: 200];
}
}
}
else
ticket = nil;
@@ -529,8 +500,7 @@ static const NSString *kJwtKey = @"jwt";
newLocation = [SOGoCASSession CASURLWithAction: @"login"
andParameters: [self _casRedirectKeys]];
casLocationCookie = [self _authLocationCookie: NO
withName: @"cas-location"
withValue: nil];
withName: @"cas-location"];
}
response = [self redirectToLocation: newLocation];
if (casCookie)
@@ -541,131 +511,6 @@ static const NSString *kJwtKey = @"jwt";
return response;
}
- (id <WOActionResults>) _openidDefaultAction: (NSString *) _domain
{
WOResponse *response;
NSString *login, *redirectLocation, *serverUrl;
NSString *sessionState, *code, *refreshTokenValue;
NSURL *newLocation, *oldLocation;
NSDictionary *formValues;
SOGoUser *loggedInUser;
WOCookie *openIdCookie, *openIdCookieLocation, *openIdRefreshCookie, *domainCookie;
WORequest *rq;
SOGoWebAuthenticator *auth;
SOGoOpenIdSession *openIdSession;
id value;
openIdCookie = nil;
openIdCookieLocation = nil;
openIdRefreshCookie = nil;
domainCookie = nil;
newLocation = nil;
rq = [context request];
//Check if the domain is stored in a cookie if not given
if(_domain == nil || [_domain length] == 0)
_domain = [rq cookieValueForKey: @"sogo-user-domain"]; //_domain can still be nil aftert his
openIdSession = [SOGoOpenIdSession OpenIdSession: _domain];
if(![openIdSession sessionIsOk])
{
return [NSException exceptionWithHTTPStatus: 502 /* Bad OpenId Configuration */
reason: [NSString stringWithFormat: @"OpenId server not found or has unexpected behavior, contact your admin."]];
}
login = [[context activeUser] login];
if ([login isEqualToString: @"anonymous"])
login = nil;
if (!login)
{
//You get here if you nerver been logged in or if you token is expired
serverUrl = [[context serverURL] absoluteString];
redirectLocation = [NSString stringWithFormat: @"%@/%@/", serverUrl, [rq applicationName]];
if((formValues = [rq formValues]) && [formValues objectForKey: @"code"])
{
//You get here if this is the callback of openid after you logged in
//NOT MANDATORY
// value = [formValues objectForKey: @"session_state"];
// if ([value isKindOfClass: [NSArray class]])
// sessionState = [value lastObject];
// else
// sessionState = value;
value = [formValues objectForKey: @"code"];
if ([value isKindOfClass: [NSArray class]])
code = [value lastObject];
else
code = value;
[openIdSession fetchToken: code redirect: redirectLocation];
login = [openIdSession login: @""];
if ([login length])
{
auth = [[WOApplication application] authenticatorInContext: context];
openIdCookie = [auth cookieWithUsername: login
andPassword: [openIdSession getToken]
inContext: context];
}
newLocation = [rq cookieValueForKey: @"openid-location"];
openIdCookieLocation = [self _authLocationCookie: YES withName: @"openid-location" withValue: nil];
domainCookie = [self _domainCookie: YES withDomain: _domain];
}
// else if((formValues = [rq formValues]) && [formValues objectForKey: @"action"])
// {
// value = [formValues objectForKey: @"action"];
// if ([value isKindOfClass: [NSArray class]])
// code = [value lastObject];
// else
// code = value;
// if([code isEqualToString:@"redirect"])
// {
// //this action onlye serve to make a redirection to openId server after a GET request
// newLocation = [openIdSession loginUrl: redirectLocation];
// }
//}
else
{
// //You get here the first time you access sogo, it redirect to last location
// if([[rq method] isEqualToString: @"POST"])
// //To avoid making a redirection to openid server after a post request, we first redirect to a get method
// newLocation = [NSString stringWithFormat: @"%@?action=redirect", redirectLocation];
// else
if(_domain != nil && [_domain length] > 0)
{
//add the domain cookie to get it after the redirect
domainCookie = [self _domainCookie: NO withDomain: _domain];
}
newLocation = [openIdSession loginUrl: redirectLocation];
openIdCookieLocation = [self _authLocationCookie: NO withName: @"openid-location" withValue: nil];
}
}
else
{
if (!newLocation)
{
oldLocation = [[self clientObject] baseURLInContext: context];
newLocation = [NSString stringWithFormat: @"%@%@", oldLocation, [login stringByEscapingURL]];
}
loggedInUser = [SOGoUser userWithLogin: login];
[self _checkAutoReloadWebCalendars: loggedInUser];
}
response = [self redirectToLocation: newLocation];
if (openIdCookie)
[response addCookie: openIdCookie];
if (openIdCookieLocation)
[response addCookie: openIdCookieLocation];
if(domainCookie)
[response addCookie: domainCookie];
//[response setStatus: 303];
return response;
}
#if defined(SAML2_CONFIG)
- (id <WOActionResults>) _saml2DefaultAction
{
@@ -689,8 +534,7 @@ static const NSString *kJwtKey = @"jwt";
newLocation = [rq cookieValueForKey: @"saml2-location"];
if (newLocation)
saml2LocationCookie = [self _authLocationCookie: YES
withName: @"saml2-location"
withValue: nil];
withName: @"saml2-location"];
else
{
oldLocation = [[self clientObject] baseURLInContext: context];
@@ -705,8 +549,7 @@ static const NSString *kJwtKey = @"jwt";
{
newLocation = [SOGoSAML2Session authenticationURLInContext: context];
saml2LocationCookie = [self _authLocationCookie: NO
withName: @"saml2-location"
withValue: nil];
withName: @"saml2-location"];
}
response = [self redirectToLocation: newLocation];
@@ -727,191 +570,43 @@ static const NSString *kJwtKey = @"jwt";
login = nil;
if (login)
{
oldLocation = [[self clientObject] baseURLInContext: context];
response = [self redirectToLocation: [NSString stringWithFormat: @"%@%@", oldLocation,
[[SOGoUser getEncryptedUsernameIfNeeded:login request: [context request]] stringByEscapingURL]]];
}
else
{
oldLocation = [[context request] uri];
if ([context clientObject] && ![oldLocation hasSuffix: @"/"] && ![oldLocation hasSuffix: @"/view"])
response = [self redirectToLocation: [NSString stringWithFormat: @"%@/", oldLocation]];
else
response = self;
}
return response;
}
- (WOResponse *) connectNameAction
{
WOResponse *response;
WORequest *request;
NSDictionary *params;
NSString *username, *language, *domain, *type, *serverUrl, *redirectLocation;
NSRange r;
request = [context request];
params = [[request contentAsString] objectFromJSONString];
username = [params objectForKey: @"userName"];
//Extract the domain
r = [username rangeOfString: @"@"];
if (r.location != NSNotFound)
{
domain = [username substringFromIndex: r.location+1];
type = [[SOGoSystemDefaults sharedSystemDefaults] getLoginTypeForDomain: domain];
if(type != nil)
{
if([type isEqualToString: @"plain"])
{
//Only reload the page with the name
serverUrl = [[context serverURL] absoluteString];
redirectLocation = [NSString stringWithFormat: @"%@/%@/login?hint=%@", serverUrl, [request applicationName], username];
//response = [self redirectToLocation: [NSString stringWithFormat: @"%@/", redirectLocation]];
response = [self responseWithStatus: 200 andJSONRepresentation:
[NSDictionary dictionaryWithObjectsAndKeys: redirectLocation, @"redirect", nil]];
}
else if([type isEqualToString: @"openid"])
{
SOGoOpenIdSession *openIdSession;
WOCookie *domainCookie, *openIdCookieLocation;
//With openId, the user will be redirected to the openid server for login
//With set the domain in a cookie to know it after the openid does the callbacl
serverUrl = [[context serverURL] absoluteString];
redirectLocation = [NSString stringWithFormat: @"%@/%@/", serverUrl, [request applicationName]];
openIdSession = [SOGoOpenIdSession OpenIdSession: domain];
domainCookie = [self _domainCookie: NO withDomain: domain];
openIdCookieLocation = [self _authLocationCookie: NO withName: @"openid-location" withValue: redirectLocation];
response = [self responseWithStatus: 200 andJSONRepresentation:
[NSDictionary dictionaryWithObjectsAndKeys: [openIdSession loginUrl: redirectLocation], @"redirect", nil]];
[response addCookie: domainCookie];
[response addCookie: openIdCookieLocation];
}
else if([type isEqualToString: @"cas"] || [type isEqualToString: @"saml2"])
{
[self logWithFormat: @"Unsupported type for now: %@", type];
response = [self responseWithStatus: 400
andString: @"Domain Authentication type not supported"];
}
oldLocation = [[self clientObject] baseURLInContext: context];
response
= [self redirectToLocation: [NSString stringWithFormat: @"%@%@",
oldLocation,
[[SOGoUser getEncryptedUsernameIfNeeded:login request: [context request]] stringByEscapingURL]]];
}
else
{
oldLocation = [[context request] uri];
if ([context clientObject]
&& ![oldLocation hasSuffix: @"/"]
&& ![oldLocation hasSuffix: @"/view"])
response = [self redirectToLocation:
[NSString stringWithFormat: @"%@/", oldLocation]];
else
{
[self logWithFormat: @"Unknown type: %@", type];
response = [self responseWithStatus: 400
andString: @"Unknwon Authentication type"];
}
response = self;
}
else
{
[self logWithFormat: @"Auth type for Domain given is not set or there is no default value: %@", domain];
response = [self responseWithStatus: 400
andString: @"Domain unknown"];
}
}
else
{
[self logWithFormat: @"Domain is required but not found for user recovery exception for user %@", username];
response = [self responseWithStatus: 400
andString: @"Domain needed in the login"];
}
return response;
}
- (id <WOActionResults>) defaultAction
{
NSString *authenticationType, *loginDomain, *type, *_domain;
SOGoSystemDefaults* sd;
NSString *authenticationType;
id <WOActionResults> result;
loginDomain = nil;
sd = [SOGoSystemDefaults sharedSystemDefaults];
if([sd doesLoginTypeByDomain])
{
NSString *login;
//In this mode sogo will ask the mail of the user before doing any authentication
//Check if a user is already logged in
_domain = [[context request] cookieValueForKey: @"sogo-user-domain"]; //_domain can still be nil aftert his
if(_domain != nil)
{
//This is a callback of an openid session.
return [self _openidDefaultAction: _domain];
}
login = [[context activeUser] login];
if ([login isEqualToString: @"anonymous"])
login = nil;
if(!login && !_domain)
return [self _standardDefaultAction];
else
{
//User already logged in. Extract the domain in that case
NSRange r;
r = [login rangeOfString: @"@"];
if (r.location != NSNotFound)
{
loginDomain = [login substringFromIndex: r.location+1];
type = [sd getLoginTypeForDomain: loginDomain];
if(type)
{
if([type isEqualToString: @"plain"])
{
result = [self _standardDefaultAction];
}
else if([type isEqualToString: @"openid"])
{
result = [self _openidDefaultAction: loginDomain];
}
else if([type isEqualToString: @"cas"] || [type isEqualToString: @"saml2"])
{
[self logWithFormat: @"Unsupported type for now: %@", type];
result = [self responseWithStatus: 400
andString: @"Domain Authentication type not supported"];
}
else
{
[self logWithFormat: @"Unknown type: %@", type];
result = [self responseWithStatus: 400
andString: @"Unknwon Authentication type"];
}
}
else
{
[self logWithFormat: @"Auth type for Domain given is not set or there is no default value: %@", loginDomain];
result = [self responseWithStatus: 400
andString: @"Domain unknown"];
}
}
else
{
loginDomain = nil;
result = [self _standardDefaultAction];
}
}
}
else {
authenticationType = [sd authenticationType];
if ([authenticationType isEqualToString: @"cas"])
result = [self _casDefaultAction];
else if ([authenticationType isEqualToString: @"openid"])
result = [self _openidDefaultAction: loginDomain];
#if defined(SAML2_CONFIG)
else if ([authenticationType isEqualToString: @"saml2"])
result = [self _saml2DefaultAction];
#endif /* SAML2_CONFIG */
else
result = [self _standardDefaultAction];
}
authenticationType = [[SOGoSystemDefaults sharedSystemDefaults]
authenticationType];
if ([authenticationType isEqualToString: @"cas"])
result = [self _casDefaultAction];
#if defined(SAML2_CONFIG)
else if ([authenticationType isEqualToString: @"saml2"])
result = [self _saml2DefaultAction];
#endif /* SAML2_CONFIG */
else
result = [self _standardDefaultAction];
return result;
}
@@ -941,57 +636,6 @@ static const NSString *kJwtKey = @"jwt";
return ([[self loginDomains] count] > 0);
}
- (BOOL) doLoginUsernameFirst
{
return [[SOGoSystemDefaults sharedSystemDefaults] doesLoginTypeByDomain];
}
- (BOOL) doFullLogin
{
//Either we directly do the full login (meaning the user inputs its username and password)
//Or we do it in two times:
//phase 1: user types its username first -> only show the username input
//phase 2: user types its password -> show all inputs
//In phase 2, the username will be in the query at key "login"
if([self doLoginUsernameFirst]){
WORequest *rq;
BOOL hasLogin;
NSDictionary *formValues;
rq = [context request];
hasLogin = ((formValues=[rq formValues]) && [formValues objectForKey: @"hint"]);
return hasLogin;
}
return YES;
}
- (BOOL) doPartialLogin
{
return ![self doFullLogin];
}
- (NSString *) getLoginHint
{
id value;
WORequest *rq;
NSString* login;
NSDictionary *formValues;
login = @"";
rq = [context request];
if((formValues=[rq formValues]) && (value=[formValues objectForKey: @"hint"]))
{
if ([value isKindOfClass: [NSArray class]])
login = [value lastObject];
else
login = value;
}
return login;
}
- (BOOL) hasPasswordRecovery
{
return [[SOGoSystemDefaults sharedSystemDefaults] isPasswordRecoveryEnabled];
@@ -1355,7 +999,8 @@ static const NSString *kJwtKey = @"jwt";
message = [[request contentAsString] objectFromJSONString];
username = [message objectForKey: @"userName"];
domain = [message objectForKey: @"domain"];
if ([[SOGoSystemDefaults sharedSystemDefaults] isPasswordRecoveryEnabled]) {
if ([[SOGoSystemDefaults sharedSystemDefaults]
isPasswordRecoveryEnabled]) {
// If no domain, try to retrieve domain from username
if (nil != domain && domain != [NSNull null]) {
domainName = domain;
@@ -1415,16 +1060,4 @@ static const NSString *kJwtKey = @"jwt";
return [[SOGoAdmin sharedInstance] getMotd] && [[[SOGoAdmin sharedInstance] getMotd] length] > 1;
}
- (BOOL) hasUrlCreateAccount
{
return ([[SOGoSystemDefaults sharedSystemDefaults]
urlCreateAccount] != nil);
}
- (NSString *) urlCreateAccount
{
return [[SOGoSystemDefaults sharedSystemDefaults]
urlCreateAccount];
}
@end /* SOGoRootPage */
+7 -28
View File
@@ -32,7 +32,6 @@
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoCASSession.h>
#import <SOGo/SOGoOpenIdSession.h>
#if defined(SAML2_CONFIG)
#import <SOGo/SOGoSAML2Session.h>
#endif
@@ -420,38 +419,18 @@
- (NSString *) _logoutRedirectURL
{
NSString *redirectURL, *login, *loginDomain, *authType;
NSString *redirectURL;
SOGoSystemDefaults *sd;
id container;
NSRange r;
login = [[context activeUser] login];
r = [login rangeOfString: @"@"];
if (r.location != NSNotFound)
loginDomain = [login substringFromIndex: r.location+1];
else
loginDomain = nil;
sd = [SOGoSystemDefaults sharedSystemDefaults];
if(loginDomain && [sd doesLoginTypeByDomain])
authType = [sd getLoginTypeForDomain: loginDomain];
else
authType = [sd authenticationType];
if ([authType isEqualToString: @"cas"])
{
redirectURL = [SOGoCASSession CASURLWithAction: @"logout"
andParameters: nil];
}
else if ([authType isEqualToString: @"openid"])
{
SOGoOpenIdSession* session;
session = [SOGoOpenIdSession OpenIdSession: loginDomain];
redirectURL = [session logoutUrl];
}
if ([[sd authenticationType] isEqualToString: @"cas"])
{
redirectURL = [SOGoCASSession CASURLWithAction: @"logout"
andParameters: nil];
}
#if defined(SAML2_CONFIG)
else if ([authType isEqualToString: @"saml2"])
else if ([[sd authenticationType] isEqualToString: @"saml2"])
{
NSString *username, *password, *domain, *value;
SOGoSAML2Session *saml2Session;
-10
View File
@@ -168,16 +168,6 @@
pageName = "SOGoRootPage";
actionName = "connect";
};
connectName = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
actionName = "connectName";
};
openid_redirect = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
actionName = "openIdRedirect";
};
changePassword = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
+278 -398
View File
@@ -12,7 +12,6 @@
<script type="text/javascript">
var cookieUsername = <var:string var:value="cookieUsername.doubleQuotedString" const:escapeHTML="NO"/>;
var language = '<var:string var:value="language" const:escapeHTML="NO"/>';
var loginHint = '<var:string var:value="getLoginHint" const:escapeHTML="NO"/>'
</script>
<!--
@@ -45,446 +44,327 @@
</div>
</var:if>
</div>
<div class="sg-login md-default-theme md-bg md-accent" flex-gt-md="50">
<var:if condition="doFullLogin">
<div id="login" class="sg-login-content md-padding">
<form name="loginForm" layout="column"
ng-cloak="ng-cloak"
ng-submit="app.login()">
<var:if condition="hasLoginSuffix">
<input type="hidden" ng-model="app.creds.loginSuffix" var:value="loginSuffix"/>
</var:if>
<div ng-if="!app.loginState">
<div id="login" class="sg-login-content md-padding">
<form name="loginForm" layout="column"
ng-cloak="ng-cloak"
ng-submit="app.login()">
<var:if condition="hasLoginSuffix">
<input type="hidden" ng-model="app.creds.loginSuffix" var:value="loginSuffix"/>
</var:if>
<div ng-if="!app.loginState">
<md-input-container class="md-block">
<label><var:string label:value="Username"/></label>
<md-icon>person</md-icon>
<input autocorrect="off" autocapitalize="off" type="text" ng-model="app.creds.username" ng-required="true" ng-change="app.usernameChanged()" ng-blur="app.retrievePasswordRecoveryEnabled()" />
</md-input-container>
<md-input-container class="md-block">
<label><var:string label:value="Password"/></label>
<md-icon>vpn_key</md-icon>
<input id="passwordField" type="password" ng-model="app.creds.password" ng-required="true"/>
<md-icon id="password-visibility-icon" ng-click="app.changePasswordVisibility()">visibility</md-icon>
</md-input-container>
<md-input-container class="md-block">
<label><var:string label:value="Username"/></label>
<md-icon>person</md-icon>
<input autocorrect="off" autocapitalize="off" type="text" ng-model="app.creds.username" ng-required="true" ng-change="app.usernameChanged()" ng-blur="app.retrievePasswordRecoveryEnabled()" />
<!-- LANGUAGES SELECT -->
<div layout="row" layout-align="start end">
<md-icon>language</md-icon>
<md-input-container class="md-flex">
<label><var:string label:value="choose"/></label>
<md-select ng-model="app.creds.language"
var:placeholder="localizedLanguage"
ng-change="app.changeLanguage($event)">
<var:foreach list="languages" item="item">
<md-option var:value="item">
<var:string value="languageText"/>
</md-option>
</var:foreach>
</md-select>
</md-input-container>
</div>
<md-input-container class="md-block">
<label><var:string label:value="Password"/></label>
<md-icon>vpn_key</md-icon>
<input id="passwordField" type="password" ng-model="app.creds.password" ng-required="true"/>
<md-icon id="password-visibility-icon" ng-click="app.changePasswordVisibility()">visibility</md-icon>
</md-input-container>
<!-- LANGUAGES SELECT -->
<!-- DOMAINS SELECT -->
<var:if condition="hasLoginDomains">
<div layout="row" layout-align="start end">
<md-icon>language</md-icon>
<md-input-container class="md-flex">
<label><var:string label:value="choose"/></label>
<md-select ng-model="app.creds.language"
var:placeholder="localizedLanguage"
ng-change="app.changeLanguage($event)">
<var:foreach list="languages" item="item">
<md-option var:value="item">
<var:string value="languageText"/>
</md-option>
</var:foreach>
</md-select>
</md-input-container>
</div>
<!-- DOMAINS SELECT -->
<var:if condition="hasLoginDomains">
<div layout="row" layout-align="start end">
<md-icon>domain</md-icon>
<md-input-container class="md-flex">
<md-select class="md-flex" ng-model="app.creds.domain" label:placeholder="choose" ng-change="app.retrievePasswordRecoveryEnabled()">
<var:foreach list="loginDomains" item="item">
<md-option var:value="item">
<var:string value="item"/>
</md-option>
</var:foreach>
</md-select>
</md-input-container>
</div>
</var:if>
<div layout="row" layout-align="center center">
<md-switch class="md-accent md-hue-2"
ng-model="app.creds.rememberLogin"
label:arial-label="Remember username">
<var:string label:value="Remember username"/>
</md-switch>
</div>
<var:if condition="hasUrlCreateAccount">
<div layout="row" layout-align="center center">
<a var:href="urlCreateAccount" target="_blank" class="create-account-link"><var:string label:value="Create an account"/></a>
</div>
</var:if>
<md-icon>domain</md-icon>
<md-input-container class="md-flex">
<md-select class="md-flex" ng-model="app.creds.domain" label:placeholder="choose" ng-change="app.retrievePasswordRecoveryEnabled()">
<var:foreach list="loginDomains" item="item">
<md-option var:value="item">
<var:string value="item"/>
</md-option>
</var:foreach>
</md-select>
</md-input-container>
</div>
</var:if>
<div layout="row" layout-align="center center">
<md-switch class="md-accent md-hue-2"
ng-model="app.creds.rememberLogin"
label:arial-label="Remember username">
<var:string label:value="Remember username"/>
</md-switch>
</div>
</div>
<!-- Password recovery -->
<div layout="row" layout-align="center center" ng-if="app.passwordRecovery.passwordRecoveryEnabled">
<div ng-if="app.showLogin">
<a href="#" ng-click="app.passwordRecoveryInfo()" sg-ripple-click="loginContent" class="password-lost-link"><var:string label:value="Password lost"/></a>
</div>
<!-- Password recovery -->
<div layout="row" layout-align="center center" ng-if="app.passwordRecovery.passwordRecoveryEnabled">
<div ng-if="app.showLogin">
<a href="#" ng-click="app.passwordRecoveryInfo()" sg-ripple-click="loginContent" class="password-lost-link"><var:string label:value="Password lost"/></a>
</div>
</div>
<!-- CONNECT BUTTON -->
<div layout="row" layout-align="space-between center" ng-if="!app.loginState">
<md-button class="md-icon-button"
label:aria-label="About"
ng-click="app.showAbout()">
<md-icon>info</md-icon>
<!-- CONNECT BUTTON -->
<div layout="row" layout-align="space-between center" ng-if="!app.loginState">
<md-button class="md-icon-button"
label:aria-label="About"
ng-click="app.showAbout()">
<md-icon>info</md-icon>
</md-button>
<div>
<md-button class="md-fab md-accent md-hue-2" type="submit"
label:aria-label="Connect"
ng-if="!app.loginState"
ng-disabled="loginForm.$invalid"
sg-ripple-click="loginContent">
<md-icon>arrow_forward</md-icon>
</md-button>
<div>
</div>
</div>
<sg-ripple class="md-default-theme md-accent md-bg"
ng-class="{ 'md-warn': app.loginState == 'error' }"><!-- ripple background --></sg-ripple>
<sg-ripple-content class="md-flex ng-hide"
layout="column" layout-align="center center" layout-fill="layout-fill"
ng-switch="app.loginState">
<!-- Authenticating -->
<div layout="column" layout-align="center center"
ng-switch-when="authenticating">
<md-progress-circular class="md-hue-1"
md-mode="indeterminate"
md-diameter="32"><!-- mailbox loading progress --></md-progress-circular>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
<var:string label:value="Authenticating"/>
</div>
</div>
<var:if condition="isTotpEnabled">
<!-- TOTP Code -->
<div layout="row" layout-align="center center" layout-fill="layout-fill"
ng-switch-when="totpcode">
<div flex="80" flex-sm="50" flex-gt-sm="40">
<md-input-container class="md-block">
<label><var:string label:value="Verification Code"/></label>
<md-icon>lock</md-icon>
<input type="text"
ng-pattern="app.verificationCodePattern"
ng-model="app.creds.verificationCode"
ng-required="app.loginState == 'totpcode'"
sg-focus-on="totpcode"/>
<div class="sg-hint"><var:string label:value="Enter the 6-digit verification code from your TOTP application."/></div>
</md-input-container>
<div layout="row" layout-align="space-between center">
<md-button class="md-icon-button"
label:aria-label="Cancel"
ng-click="app.restoreLogin()"
sg-ripple-click="loginContent">
<md-icon>arrow_backward</md-icon>
</md-button>
<md-button class="md-fab md-accent md-hue-2" type="submit"
label:aria-label="Connect"
ng-if="!app.loginState"
ng-if="app.loginState == 'totpcode'"
ng-disabled="loginForm.$invalid"
sg-ripple-click="loginContent">
ng-click="app.login()">
<md-icon>arrow_forward</md-icon>
</md-button>
</div>
</div>
<sg-ripple class="md-default-theme md-accent md-bg"
ng-class="{ 'md-warn': app.loginState == 'error' }"><!-- ripple background --></sg-ripple>
<sg-ripple-content class="md-flex ng-hide"
layout="column" layout-align="center center" layout-fill="layout-fill"
ng-switch="app.loginState">
<!-- Authenticating -->
<div layout="column" layout-align="center center"
ng-switch-when="authenticating">
<md-progress-circular class="md-hue-1"
md-mode="indeterminate"
md-diameter="32"><!-- mailbox loading progress --></md-progress-circular>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
<var:string label:value="Authenticating"/>
</div>
<!-- TOTP has been disabled -->
<div layout="row" layout-align="center center" layout-fill="layout-fill"
ng-switch-when="totpdisabled">
<div layout="column" layout-align="center center" flex-xs="flex-xs" flex-gt-xs="50">
<md-icon class="md-accent md-hue-1 sg-icon--large">warning</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding" ng-if="app.cn">
<var:string label:value="Welcome"/> {{app.cn}}
</div>
<div class="md-padding" layout="row" layout-align="start center">
<md-icon>priority_high</md-icon>
<div class="md-padding">
<var:string label:value="Two-factor authentication has been disabled. Visit the Preferences module to restore two-factor authentication and reconfigure your TOTP application."/>
</div>
</div>
<div layout="row" layout-align="end center">
<md-button
ng-click="app.continueLogin()"
sg-ripple-click="loginContent"><var:string label:value="Continue"/></md-button>
</div>
</div>
</div>
</var:if>
<var:if condition="isTotpEnabled">
<!-- TOTP Code -->
<div layout="row" layout-align="center center" layout-fill="layout-fill"
ng-switch-when="totpcode">
<div flex="80" flex-sm="50" flex-gt-sm="40">
<md-input-container class="md-block">
<label><var:string label:value="Verification Code"/></label>
<md-icon>lock</md-icon>
<input type="text"
ng-pattern="app.verificationCodePattern"
ng-model="app.creds.verificationCode"
ng-required="app.loginState == 'totpcode'"
sg-focus-on="totpcode"/>
<div class="sg-hint"><var:string label:value="Enter the 6-digit verification code from your TOTP application."/></div>
<!-- Password policy: Password is expired / password recovery-->
<div layout="column" layout-align="center center"
ng-switch-when="passwordchange">
<md-icon class="md-accent md-hue-1 sg-icon--large" ng-if="!app.isInPasswordRecoveryMode()">watch_later</md-icon>
<md-icon class="md-accent md-hue-1 sg-icon--large" ng-if="app.isInPasswordRecoveryMode()">vpn_key</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding" ng-if="!app.isInPasswordRecoveryMode()">
<var:string label:value="Your password has expired, please enter a new one below"/>
</div>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding" ng-if="app.isInPasswordRecoveryMode()">
<var:string label:value="Please enter a new password below"/>
</div>
<div flex="100">
<div layout="row" layout-xs="column">
<md-input-container class="md-block" flex="flex" ng-if="!app.isInPasswordRecoveryMode()">
<label><var:string label:value="Current password"/>
</label>
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.oldPassword"/>
</md-input-container>
<div layout="row" layout-align="space-between center">
<md-button class="md-icon-button"
label:aria-label="Cancel"
ng-click="app.restoreLogin()"
sg-ripple-click="loginContent">
<md-icon>arrow_backward</md-icon>
</md-button>
<md-button class="md-fab md-accent md-hue-2" type="submit"
label:aria-label="Connect"
ng-if="app.loginState == 'totpcode'"
ng-disabled="loginForm.$invalid"
ng-click="app.login()">
<md-icon>arrow_forward</md-icon>
</md-button>
</div>
<md-input-container class="md-block" flex="flex">
<label><var:string label:value="New password"/>
</label>
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.newPassword"/>
</md-input-container>
<md-input-container class="md-block" flex="flex">
<label><var:string label:value="Confirmation"/>
</label>
<input type="password" name="newPasswordConfirmation" sg-no-dirty-check="true" ng-model="app.passwords.newPasswordConfirmation"/>
<div ng-messages="loginForm.newPasswordConfirmation.$error">
<div ng-message="newPasswordMismatch"><var:string label:value="Passwords don't match"/></div>
</div>
</md-input-container>
</div>
<div layout="row" layout-align="end center">
<md-button ng-click="app.changePassword()" type="button" ng-disabled="!app.canChangePassword(loginForm)">
<var:string label:value="Change"/>
</md-button>
</div>
</div>
<!-- TOTP has been disabled -->
<div layout="row" layout-align="center center" layout-fill="layout-fill"
ng-switch-when="totpdisabled">
<div layout="column" layout-align="center center" flex-xs="flex-xs" flex-gt-xs="50">
<md-icon class="md-accent md-hue-1 sg-icon--large">warning</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding" ng-if="app.cn">
<var:string label:value="Welcome"/> {{app.cn}}
</div>
<div class="md-padding" layout="row" layout-align="start center">
<md-icon>priority_high</md-icon>
<div class="md-padding">
<var:string label:value="Two-factor authentication has been disabled. Visit the Preferences module to restore two-factor authentication and reconfigure your TOTP application."/>
</div>
</div>
<div layout="row" layout-align="end center">
<md-button
ng-click="app.continueLogin()"
</div>
<!-- Password policy: Grace period -->
<div layout="row" layout-align="center center" layout-fill="layout-fill"
ng-switch-when="passwordwillexpire">
<div layout="column" layout-align="center center" flex-xs="flex-xs" flex-gt-xs="50">
<md-icon class="md-accent md-hue-1 sg-icon--large">warning</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding" ng-if="app.cn">
<var:string label:value="Welcome"/> {{app.cn}}
</div>
<div class="md-padding" layout="row" layout-align="start center">
<md-icon>priority_high</md-icon>
<div class="md-padding">{{app.errorMessage}}</div>
</div>
<div layout="row" layout-align="end center">
<md-button
ng-click="app.loginState = 'passwordexpired'"><var:string label:value="Change your Password"/></md-button>
<md-button
ng-click="app.continueLogin()"
sg-ripple-click="loginContent"><var:string label:value="Continue"/></md-button>
</div>
</div>
</div>
<!-- Password recovery -->
<var:if condition="hasPasswordRecovery">
<div layout="column" layout-align="center center"
ng-switch-when="passwordrecovery">
<md-icon class="md-accent md-hue-1 sg-icon--large">vpn_key</md-icon>
<div flex="100">
<div layout="row" layout-xs="column" class="md-padding" layout-align="center center">
<div ng-if="app.passwordRecovery.showLoader">
<md-progress-circular class="md-hue-1"
md-mode="indeterminate"
md-diameter="32"><!-- password recovery progress --></md-progress-circular>
</div>
<div ng-if="'SecretQuestion' === app.passwordRecovery.passwordRecoveryMode">
<div ng-if="!app.passwordRecovery.showLoader">
{{ app.passwordRecovery.passwordRecoveryQuestion }}
<md-input-container class="md-block">
<label><var:string label:value="Answer"/></label>
<input autocorrect="off" autocapitalize="off" type="text" ng-model="app.passwordRecovery.passwordRecoveryQuestionAnswer" />
</md-input-container>
</div>
</div>
<div ng-if="'SecondaryEmail' === app.passwordRecovery.passwordRecoveryMode">
<div ng-if="!app.passwordRecovery.showLoader">
{{ app.passwordRecovery.passwordRecoverySecondaryEmailText }}
</div>
</div>
</div>
<div layout="row" layout-align="end center" ng-if="!app.passwordRecovery.showLoader">
<md-button ng-click="app.passwordRecoveryAbort()" type="button" >
<var:string label:value="Back"/>
</md-button>
<div ng-if="'SecretQuestion' === app.passwordRecovery.passwordRecoveryMode">
<md-button ng-click="app.passwordRecoveryCheck()" type="button" >
<var:string label:value="Next"/>
</md-button>
</div>
<div ng-if="'SecondaryEmail' === app.passwordRecovery.passwordRecoveryMode">
<md-button ng-click="app.passwordRecoveryEmail()" type="button" >
<var:string label:value="Next"/>
</md-button>
</div>
</div>
</div>
</div>
</var:if>
<!-- Password policy: Password is expired / password recovery-->
<div layout="column" layout-align="center center"
ng-switch-when="passwordchange">
<md-icon class="md-accent md-hue-1 sg-icon--large" ng-if="!app.isInPasswordRecoveryMode()">watch_later</md-icon>
<md-icon class="md-accent md-hue-1 sg-icon--large" ng-if="app.isInPasswordRecoveryMode()">vpn_key</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding" ng-if="!app.isInPasswordRecoveryMode()">
<var:string label:value="Your password has expired, please enter a new one below"/>
</div>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding" ng-if="app.isInPasswordRecoveryMode()">
<var:string label:value="Please enter a new password below"/>
</div>
ng-switch-when="sendrecoverymail">
<md-icon class="md-accent md-hue-1 sg-icon--large">local_shipping</md-icon>
<div flex="100">
<div layout="row" layout-xs="column">
<md-input-container class="md-block" flex="flex" ng-if="!app.isInPasswordRecoveryMode()">
<label><var:string label:value="Current password"/>
</label>
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.oldPassword"/>
</md-input-container>
<md-input-container class="md-block" flex="flex">
<label><var:string label:value="New password"/>
</label>
<input type="password" sg-no-dirty-check="true" ng-model="app.passwords.newPassword"/>
</md-input-container>
<md-input-container class="md-block" flex="flex">
<label><var:string label:value="Confirmation"/>
</label>
<input type="password" name="newPasswordConfirmation" sg-no-dirty-check="true" ng-model="app.passwords.newPasswordConfirmation"/>
<div ng-messages="loginForm.newPasswordConfirmation.$error">
<div ng-message="newPasswordMismatch"><var:string label:value="Passwords don't match"/></div>
</div>
</md-input-container>
<div layout="row" layout-xs="column" class="md-padding">
<div ng-if="'SecondaryEmail' === app.passwordRecovery.passwordRecoveryMode">
<var:string label:value="A password reset link has been sent, please check your recovery e-mail mailbox and click on the link"/>
</div>
</div>
<div layout="row" layout-align="end center">
<md-button ng-click="app.changePassword()" type="button" ng-disabled="!app.canChangePassword(loginForm)">
<var:string label:value="Change"/>
<md-button ng-click="app.passwordRecoveryAbort()" type="button" >
<var:string label:value="Back"/>
</md-button>
</div>
</div>
</div>
</var:if>
<!-- Password policy: Grace period -->
<div layout="row" layout-align="center center" layout-fill="layout-fill"
ng-switch-when="passwordwillexpire">
<div layout="column" layout-align="center center" flex-xs="flex-xs" flex-gt-xs="50">
<md-icon class="md-accent md-hue-1 sg-icon--large">warning</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding" ng-if="app.cn">
<var:string label:value="Welcome"/> {{app.cn}}
</div>
<div class="md-padding" layout="row" layout-align="start center">
<md-icon>priority_high</md-icon>
<div class="md-padding">{{app.errorMessage}}</div>
</div>
<div layout="row" layout-align="end center">
<md-button
ng-click="app.loginState = 'passwordexpired'"><var:string label:value="Change your Password"/></md-button>
<md-button
ng-click="app.continueLogin()"
sg-ripple-click="loginContent"><var:string label:value="Continue"/></md-button>
</div>
</div>
<!-- Logged in -->
<div layout="column" layout-align="center center"
ng-switch-when="logged">
<md-icon class="md-accent md-hue-1 sg-icon--large">done</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
<var:string label:value="Welcome"/> {{app.cn}}
</div>
</div>
<!-- Password recovery -->
<var:if condition="hasPasswordRecovery">
<div layout="column" layout-align="center center"
ng-switch-when="passwordrecovery">
<md-icon class="md-accent md-hue-1 sg-icon--large">vpn_key</md-icon>
<div flex="100">
<div layout="row" layout-xs="column" class="md-padding" layout-align="center center">
<div ng-if="app.passwordRecovery.showLoader">
<md-progress-circular class="md-hue-1"
md-mode="indeterminate"
md-diameter="32"><!-- password recovery progress --></md-progress-circular>
</div>
<div ng-if="'SecretQuestion' === app.passwordRecovery.passwordRecoveryMode">
<div ng-if="!app.passwordRecovery.showLoader">
{{ app.passwordRecovery.passwordRecoveryQuestion }}
<md-input-container class="md-block">
<label><var:string label:value="Answer"/></label>
<input autocorrect="off" autocapitalize="off" type="text" ng-model="app.passwordRecovery.passwordRecoveryQuestionAnswer" />
</md-input-container>
</div>
</div>
<div ng-if="'SecondaryEmail' === app.passwordRecovery.passwordRecoveryMode">
<div ng-if="!app.passwordRecovery.showLoader">
{{ app.passwordRecovery.passwordRecoverySecondaryEmailText }}
</div>
</div>
</div>
<div layout="row" layout-align="end center" ng-if="!app.passwordRecovery.showLoader">
<md-button ng-click="app.passwordRecoveryAbort()" type="button" >
<var:string label:value="Back"/>
</md-button>
<div ng-if="'SecretQuestion' === app.passwordRecovery.passwordRecoveryMode">
<md-button ng-click="app.passwordRecoveryCheck()" type="button" >
<var:string label:value="Next"/>
</md-button>
</div>
<div ng-if="'SecondaryEmail' === app.passwordRecovery.passwordRecoveryMode">
<md-button ng-click="app.passwordRecoveryEmail()" type="button" >
<var:string label:value="Next"/>
</md-button>
</div>
</div>
</div>
</div>
<div layout="column" layout-align="center center"
ng-switch-when="sendrecoverymail">
<md-icon class="md-accent md-hue-1 sg-icon--large">local_shipping</md-icon>
<div flex="100">
<div layout="row" layout-xs="column" class="md-padding">
<div ng-if="'SecondaryEmail' === app.passwordRecovery.passwordRecoveryMode">
<var:string label:value="A password reset link has been sent, please check your recovery e-mail mailbox and click on the link"/>
</div>
</div>
<div layout="row" layout-align="end center">
<md-button ng-click="app.passwordRecoveryAbort()" type="button" >
<var:string label:value="Back"/>
</md-button>
</div>
</div>
</div>
</var:if>
<!-- Logged in -->
<div layout="column" layout-align="center center"
ng-switch-when="logged">
<md-icon class="md-accent md-hue-1 sg-icon--large">done</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
<var:string label:value="Welcome"/> {{app.cn}}
</div>
<div layout="column" layout-align="center center"
ng-switch-when="message">
<md-icon class="md-accent md-hue-1 sg-icon--large">done</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
{{app.errorMessage}}
</div>
<md-button
ng-click="app.continueLogin()"
sg-ripple-click="loginContent"><var:string label:value="Continue"/></md-button>
</div>
<div layout="column" layout-align="center center"
ng-switch-when="message">
<md-icon class="md-accent md-hue-1 sg-icon--large">done</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
{{app.errorMessage}}
</div>
<md-button
ng-click="app.continueLogin()"
sg-ripple-click="loginContent"><var:string label:value="Continue"/></md-button>
<!-- Error -->
<div layout="column" layout-align="center center"
ng-switch-when="error">
<md-icon class="md-accent md-hue-1 sg-icon--large">error</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
{{app.errorMessage}}
</div>
<md-button
ng-click="app.restoreLogin()"
sg-ripple-click="loginContent"><var:string label:value="Retry"/></md-button>
</div>
<!-- Error -->
<div layout="column" layout-align="center center"
ng-switch-when="error">
<md-icon class="md-accent md-hue-1 sg-icon--large">error</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
{{app.errorMessage}}
</div>
<md-button
ng-click="app.restoreLogin()"
sg-ripple-click="loginContent"><var:string label:value="Retry"/></md-button>
</div>
</sg-ripple-content>
</form>
</sg-ripple-content>
</form>
</div>
</var:if>
<var:if condition="doPartialLogin">
<div id="login" class="sg-login-content md-padding">
<form name="loginForm" layout="column"
ng-cloak="ng-cloak"
ng-submit="app.loginName()">
<div ng-if="!app.loginState">
<md-input-container class="md-block">
<label><var:string label:value="Username"/></label>
<md-icon>person</md-icon>
<input autocorrect="off" autocapitalize="off" type="text" ng-model="app.creds.username" ng-required="true" ng-change="app.usernameChanged()" ng-blur="app.retrievePasswordRecoveryEnabled()" />
</md-input-container>
<!-- LANGUAGES SELECT -->
<div layout="row" layout-align="start end">
<md-icon>language</md-icon>
<md-input-container class="md-flex">
<label><var:string label:value="choose"/></label>
<md-select ng-model="app.creds.language"
var:placeholder="localizedLanguage"
ng-change="app.changeLanguage($event)">
<var:foreach list="languages" item="item">
<md-option var:value="item">
<var:string value="languageText"/>
</md-option>
</var:foreach>
</md-select>
</md-input-container>
</div>
<var:if condition="hasUrlCreateAccount">
<div layout="row" layout-align="center center">
<a var:href="urlCreateAccount" target="_blank" class="create-account-link"><var:string label:value="Create an account"/></a>
</div>
</var:if>
</div>
<!-- CONNECT BUTTON -->
<div layout="row" layout-align="space-between center" ng-if="!app.loginState">
<md-button class="md-icon-button"
label:aria-label="About"
ng-click="app.showAbout()">
<md-icon>info</md-icon>
</md-button>
<div>
<md-button class="md-fab md-accent md-hue-2" type="submit"
label:aria-label="Connect"
ng-if="!app.loginState"
ng-disabled="loginForm.$invalid"
sg-ripple-click="loginContent">
<md-icon>arrow_forward</md-icon>
</md-button>
</div>
</div>
<sg-ripple class="md-default-theme md-accent md-bg"
ng-class="{ 'md-warn': app.loginState == 'error' }"><!-- ripple background --></sg-ripple>
<sg-ripple-content class="md-flex ng-hide"
layout="column" layout-align="center center" layout-fill="layout-fill"
ng-switch="app.loginState">
<!-- Authenticating -->
<div layout="column" layout-align="center center"
ng-switch-when="authenticating">
<md-progress-circular class="md-hue-1"
md-mode="indeterminate"
md-diameter="32"><!-- mailbox loading progress --></md-progress-circular>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
<var:string label:value="Authenticating"/>
</div>
</div>
<!-- Logged in -->
<div layout="column" layout-align="center center"
ng-switch-when="logged">
<md-icon class="md-accent md-hue-1 sg-icon--large">done</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
<var:string label:value="Welcome"/> {{app.cn}}
</div>
</div>
<div layout="column" layout-align="center center"
ng-switch-when="message">
<md-icon class="md-accent md-hue-1 sg-icon--large">done</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
{{app.errorMessage}}
</div>
<md-button
ng-click="app.continueLogin()"
sg-ripple-click="loginContent"><var:string label:value="Continue"/></md-button>
</div>
<!-- Error -->
<div layout="column" layout-align="center center"
ng-switch-when="error">
<md-icon class="md-accent md-hue-1 sg-icon--large">error</md-icon>
<div class="md-default-theme md-accent md-hue-1 md-fg md-padding">
{{app.errorMessage}}
</div>
<md-button
ng-click="app.restoreLogin()"
sg-ripple-click="loginContent"><var:string label:value="Retry"/></md-button>
</div>
</sg-ripple-content>
</form>
</div>
</var:if>
</div>
</div>
</div>
</md-content>
+1 -1
View File
@@ -1,2 +1,2 @@
@charset "UTF-8";.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.sg-hide{opacity:0}@-moz-document url-prefix(){[layout-fill]{margin:0;width:100%;min-height:100%;height:100%}}[flex-order]{-webkit-box-ordinal-group:1;-webkit-order:0;order:0}[flex-order="-20"]{-webkit-box-ordinal-group:-19;-webkit-order:-20;order:-20}[flex-order="-19"]{-webkit-box-ordinal-group:-18;-webkit-order:-19;order:-19}[flex-order="-18"]{-webkit-box-ordinal-group:-17;-webkit-order:-18;order:-18}[flex-order="-17"]{-webkit-box-ordinal-group:-16;-webkit-order:-17;order:-17}[flex-order="-16"]{-webkit-box-ordinal-group:-15;-webkit-order:-16;order:-16}[flex-order="-15"]{-webkit-box-ordinal-group:-14;-webkit-order:-15;order:-15}[flex-order="-14"]{-webkit-box-ordinal-group:-13;-webkit-order:-14;order:-14}[flex-order="-13"]{-webkit-box-ordinal-group:-12;-webkit-order:-13;order:-13}[flex-order="-12"]{-webkit-box-ordinal-group:-11;-webkit-order:-12;order:-12}[flex-order="-11"]{-webkit-box-ordinal-group:-10;-webkit-order:-11;order:-11}[flex-order="-10"]{-webkit-box-ordinal-group:-9;-webkit-order:-10;order:-10}[flex-order="-9"]{-webkit-box-ordinal-group:-8;-webkit-order:-9;order:-9}[flex-order="-8"]{-webkit-box-ordinal-group:-7;-webkit-order:-8;order:-8}[flex-order="-7"]{-webkit-box-ordinal-group:-6;-webkit-order:-7;order:-7}[flex-order="-6"]{-webkit-box-ordinal-group:-5;-webkit-order:-6;order:-6}[flex-order="-5"]{-webkit-box-ordinal-group:-4;-webkit-order:-5;order:-5}[flex-order="-4"]{-webkit-box-ordinal-group:-3;-webkit-order:-4;order:-4}[flex-order="-3"]{-webkit-box-ordinal-group:-2;-webkit-order:-3;order:-3}[flex-order="-2"]{-webkit-box-ordinal-group:-1;-webkit-order:-2;order:-2}[flex-order="-1"]{-webkit-box-ordinal-group:0;-webkit-order:-1;order:-1}[flex-order="0"]{-webkit-box-ordinal-group:1;-webkit-order:0;order:0}[flex-order="1"]{-webkit-box-ordinal-group:2;-webkit-order:1;order:1}[flex-order="2"]{-webkit-box-ordinal-group:3;-webkit-order:2;order:2}[flex-order="3"]{-webkit-box-ordinal-group:4;-webkit-order:3;order:3}[flex-order="4"]{-webkit-box-ordinal-group:5;-webkit-order:4;order:4}[flex-order="5"]{-webkit-box-ordinal-group:6;-webkit-order:5;order:5}[flex-order="6"]{-webkit-box-ordinal-group:7;-webkit-order:6;order:6}[flex-order="7"]{-webkit-box-ordinal-group:8;-webkit-order:7;order:7}[flex-order="8"]{-webkit-box-ordinal-group:9;-webkit-order:8;order:8}[flex-order="9"]{-webkit-box-ordinal-group:10;-webkit-order:9;order:9}[flex-order="10"]{-webkit-box-ordinal-group:11;-webkit-order:10;order:10}[flex-order="11"]{-webkit-box-ordinal-group:12;-webkit-order:11;order:11}[flex-order="12"]{-webkit-box-ordinal-group:13;-webkit-order:12;order:12}[flex-order="13"]{-webkit-box-ordinal-group:14;-webkit-order:13;order:13}[flex-order="14"]{-webkit-box-ordinal-group:15;-webkit-order:14;order:14}[flex-order="15"]{-webkit-box-ordinal-group:16;-webkit-order:15;order:15}[flex-order="16"]{-webkit-box-ordinal-group:17;-webkit-order:16;order:16}[flex-order="17"]{-webkit-box-ordinal-group:18;-webkit-order:17;order:17}[flex-order="18"]{-webkit-box-ordinal-group:19;-webkit-order:18;order:18}[flex-order="19"]{-webkit-box-ordinal-group:20;-webkit-order:19;order:19}[flex-order="20"]{-webkit-box-ordinal-group:21;-webkit-order:20;order:20}[flex-offset="0"]{margin-left:0}[flex-offset="5"]{margin-left:5%}[flex-offset="10"]{margin-left:10%}[flex-offset="15"]{margin-left:15%}[flex-offset="20"]{margin-left:20%}[flex-offset="25"]{margin-left:25%}[flex-offset="30"]{margin-left:30%}[flex-offset="35"]{margin-left:35%}[flex-offset="40"]{margin-left:40%}[flex-offset="45"]{margin-left:45%}[flex-offset="50"]{margin-left:50%}[flex-offset="55"]{margin-left:55%}[flex-offset="60"]{margin-left:60%}[flex-offset="65"]{margin-left:65%}[flex-offset="70"]{margin-left:70%}[flex-offset="75"]{margin-left:75%}[flex-offset="80"]{margin-left:80%}[flex-offset="85"]{margin-left:85%}[flex-offset="90"]{margin-left:90%}[flex-offset="95"]{margin-left:95%}[flex-offset="33"]{margin-left:33.3333333333%}[flex-offset="66"]{margin-left:66.6666666667%}[layout-align="start stretch"],[layout-align]{-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-align-content:stretch;align-content:stretch;-webkit-box-align:stretch;-webkit-align-items:stretch;align-items:stretch}[layout-align="start center"],[layout-align="start end"],[layout-align="start start"],[layout-align="start stretch"],[layout-align=start]{-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}[layout-align="center center"],[layout-align="center end"],[layout-align="center start"],[layout-align="center stretch"],[layout-align=center]{-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}[layout-align="end center"],[layout-align="end end"],[layout-align="end start"],[layout-align="end stretch"],[layout-align=end]{-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}[layout-align="spacLine truncated
@charset "UTF-8";.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.sg-hide{opacity:0}@-moz-document url-prefix(){[layout-fill]{margin:0;width:100%;min-height:100%;height:100%}}[flex-order]{-webkit-box-ordinal-group:1;-webkit-order:0;order:0}[flex-order="-20"]{-webkit-box-ordinal-group:-19;-webkit-order:-20;order:-20}[flex-order="-19"]{-webkit-box-ordinal-group:-18;-webkit-order:-19;order:-19}[flex-order="-18"]{-webkit-box-ordinal-group:-17;-webkit-order:-18;order:-18}[flex-order="-17"]{-webkit-box-ordinal-group:-16;-webkit-order:-17;order:-17}[flex-order="-16"]{-webkit-box-ordinal-group:-15;-webkit-order:-16;order:-16}[flex-order="-15"]{-webkit-box-ordinal-group:-14;-webkit-order:-15;order:-15}[flex-order="-14"]{-webkit-box-ordinal-group:-13;-webkit-order:-14;order:-14}[flex-order="-13"]{-webkit-box-ordinal-group:-12;-webkit-order:-13;order:-13}[flex-order="-12"]{-webkit-box-ordinal-group:-11;-webkit-order:-12;order:-12}[flex-order="-11"]{-webkit-box-ordinal-group:-10;-webkit-order:-11;order:-11}[flex-order="-10"]{-webkit-box-ordinal-group:-9;-webkit-order:-10;order:-10}[flex-order="-9"]{-webkit-box-ordinal-group:-8;-webkit-order:-9;order:-9}[flex-order="-8"]{-webkit-box-ordinal-group:-7;-webkit-order:-8;order:-8}[flex-order="-7"]{-webkit-box-ordinal-group:-6;-webkit-order:-7;order:-7}[flex-order="-6"]{-webkit-box-ordinal-group:-5;-webkit-order:-6;order:-6}[flex-order="-5"]{-webkit-box-ordinal-group:-4;-webkit-order:-5;order:-5}[flex-order="-4"]{-webkit-box-ordinal-group:-3;-webkit-order:-4;order:-4}[flex-order="-3"]{-webkit-box-ordinal-group:-2;-webkit-order:-3;order:-3}[flex-order="-2"]{-webkit-box-ordinal-group:-1;-webkit-order:-2;order:-2}[flex-order="-1"]{-webkit-box-ordinal-group:0;-webkit-order:-1;order:-1}[flex-order="0"]{-webkit-box-ordinal-group:1;-webkit-order:0;order:0}[flex-order="1"]{-webkit-box-ordinal-group:2;-webkit-order:1;order:1}[flex-order="2"]{-webkit-box-ordinal-group:3;-webkit-order:2;order:2}[flex-order="3"]{-webkit-box-ordinal-group:4;-webkit-order:3;order:3}[flex-order="4"]{-webkit-box-ordinal-group:5;-webkit-order:4;order:4}[flex-order="5"]{-webkit-box-ordinal-group:6;-webkit-order:5;order:5}[flex-order="6"]{-webkit-box-ordinal-group:7;-webkit-order:6;order:6}[flex-order="7"]{-webkit-box-ordinal-group:8;-webkit-order:7;order:7}[flex-order="8"]{-webkit-box-ordinal-group:9;-webkit-order:8;order:8}[flex-order="9"]{-webkit-box-ordinal-group:10;-webkit-order:9;order:9}[flex-order="10"]{-webkit-box-ordinal-group:11;-webkit-order:10;order:10}[flex-order="11"]{-webkit-box-ordinal-group:12;-webkit-order:11;order:11}[flex-order="12"]{-webkit-box-ordinal-group:13;-webkit-order:12;order:12}[flex-order="13"]{-webkit-box-ordinal-group:14;-webkit-order:13;order:13}[flex-order="14"]{-webkit-box-ordinal-group:15;-webkit-order:14;order:14}[flex-order="15"]{-webkit-box-ordinal-group:16;-webkit-order:15;order:15}[flex-order="16"]{-webkit-box-ordinal-group:17;-webkit-order:16;order:16}[flex-order="17"]{-webkit-box-ordinal-group:18;-webkit-order:17;order:17}[flex-order="18"]{-webkit-box-ordinal-group:19;-webkit-order:18;order:18}[flex-order="19"]{-webkit-box-ordinal-group:20;-webkit-order:19;order:19}[flex-order="20"]{-webkit-box-ordinal-group:21;-webkit-order:20;order:20}[flex-offset="0"]{margin-left:0}[flex-offset="5"]{margin-left:5%}[flex-offset="10"]{margin-left:10%}[flex-offset="15"]{margin-left:15%}[flex-offset="20"]{margin-left:20%}[flex-offset="25"]{margin-left:25%}[flex-offset="30"]{margin-left:30%}[flex-offset="35"]{margin-left:35%}[flex-offset="40"]{margin-left:40%}[flex-offset="45"]{margin-left:45%}[flex-offset="50"]{margin-left:50%}[flex-offset="55"]{margin-left:55%}[flex-offset="60"]{margin-left:60%}[flex-offset="65"]{margin-left:65%}[flex-offset="70"]{margin-left:70%}[flex-offset="75"]{margin-left:75%}[flex-offset="80"]{margin-left:80%}[flex-offset="85"]{margin-left:85%}[flex-offset="90"]{margin-left:90%}[flex-offset="95"]{margin-left:95%}[flex-offset="33"]{margin-left:33.3333333333%}[flex-offset="66"]{margin-left:66.6666666667%}[layout-align="start stretch"],[layout-align]{-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-align-content:stretch;align-content:stretch;-webkit-box-align:stretch;-webkit-align-items:stretch;align-items:stretch}[layout-align="start center"],[layout-align="start end"],[layout-align="start start"],[layout-align="start stretch"],[layout-align=start]{-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}[layout-align="center center"],[layout-align="center end"],[layout-align="center start"],[layout-align="center stretch"],[layout-align=center]{-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}[layout-align="end center"],[layout-align="end end"],[layout-align="end start"],[layout-align="end stretch"],[layout-align=end]{-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}[layout-align="spacLine truncated
/*# sourceMappingURL=styles.css.map */
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["css/styles.css"],"names":[],"mappings":"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 truncated
{"version":3,"sources":["css/styles.css"],"names":[],"mappings":"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 truncated
+1 -1
View File
@@ -1,2 +1,2 @@
function l(){var n,e,t=arguments[0],o=t,r=arguments;for(labels[t]?o=labels[t]:clabels[t]&&(o=clabels[t]),n=1,e=0;n<r.length;n++,e++)o=o.replace("%{"+e+"}",r[n]);return o=(n=1)<r.length?o.replace(/%((%)|s|d)/g,function(e){var t=null;return e[2]?t=e[2]:(t=r[n],"%d"===e&&(t=parseFloat(t),isNaN(t))&&(t=0),n++),t}):o}function hexToRgb(e){e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:null}function contrast(e){var t=1,e=hexToRgb(e);if(e){for(var n=[e.r/255,e.g/255,e.b/255],o=0;o<n.length;++o)n[o]=n[o]<=.03928?n[o]/12.92:Math.pow((n[o]+.055)/1.055,2.4);t=.2126*n[0]+.7152*n[1]+.0722*n[2]}return.179<t?"black":"white"}function guid(){function e(){return(65536*(1+Math.random())|0).toString(16).substring(1)}return(e()+e()+"-"+e()+"-4"+e().substr(0,3)+"-"+e()+"-"+e()+e()+e()).toLowerCase()}!function(){"use strict";function e(e,t,n,o,r,i,s){e.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/),r.definePalette("sogo-green",{50:"eaf5e9",100:"cbe5c8",200:"aad6a5",300:"88c781",400:"66b86a",500:"56b04c",600:"4da143",700:"388e3c",800:"367d2e",900:"225e1b",A100:"fafafa",A200:"69f0ae",A400:"00e676",A700:"00c853",contrastDefaultColor:"dark",contrastLightColors:["300","400","500","600","700","800","900"]}),r.definePalette("sogo-blue",{50:"f0faf9",100:"e1f5f3",200:"ceebe8",300:"bfe0dd",400:"b2d6d3",500:"a1ccc8",600:"8ebfbb",700:"7db3b0",800:"639997",900:"4d8080",A100:"d4f7fa",A200:"c3f5fa",A400:"53e3f0",A700:"00b0c0",contrastDefaultColor:"light",contrastDarkColors:["50","100","200"]});e=r.extendPalette("grey",{1e3:"baa870"});r.definePalette("sogo-grey",e),r.theme("default").primaryPalette("sogo-blue",{default:"900","hue-1":"400","hue-2":"800","hue-3":"A700"}).accentPalette("sogo-green",{default:"500","hue-1":"A100","hue-2":"300","hue-3":"A700"}).backgroundPalette("sogo-grey"),r.registerStyles(["md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent,","md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-input-container[md-no-float] .md-input {"," background-color: '{{accent-hue-1}}';"," color: '{{foreground-1}}';","}","md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-icon {"," color: '{{foreground-1}}';"," fill: '{{foreground-1}}';","}"].join("")),r.registerStyles([".md-autocomplete-suggestions.md-3-line li p {"," color: '{{foreground-2}}';","}"].join("")),r.registerStyles([".sg-time-selection-indicator.sg-time-selected,",".sg-time-selection-indicator:hover.sg-time-selected,",".sg-time-selection-indicator.md-focus.sg-time-selected {"," background: '{{primary-500}}';","}",".sg-timepicker-open .sg-timepicker-icon {"," color: '{{primary-900}}';","}",".sg-timepicker-time,",".sg-timepicker-open .sg-timepicker-input-container {"," background: '{{background-hue-1}}';","}",".sg-timepicker-input-mask-opaque {"," box-shadow: 0 0 0 9999px '{{background-hue-1}}';","}"].join("")),r.registerStyles(["[ui-view=calendars] .hours {"," color: '{{primary-700}}';","}",".attendees .busy {"," background-color: '{{background-1000}}';","}",".attendees .event {"," background-color: '{{primary-300}}';","}"].join("")),r.registerStyles([".sg-message-thread {"," background-color: '{{primary-100}}';","}",".sg-message-thread-first {"," background-color: '{{primary-200}}';","}"].join("")),window.DebugEnabled||(t.debugEnabled(!1),n.debugInfoEnabled(!1),i.disableWarnings(),s.errorOnUnhandledRejections(!1),r.generateThemesOnDemand(!0)),o.interceptors.push("AuthInterceptor"),o.interceptors.push("ErrorInterceptor")}function a(t,e,n,o,r){var i=e.defer(),s=angular.element('<iframe class="ng-hide" src="'+t.UserFolderURL+'recover"></iframe>');return s.on("load",function(){var e=o.get("$state");2<r.config.attempt?(angular.element(t).off("beforeunload"),t.location.href=t.ApplicationBaseURL+e.href(e.current),i.reject()):n(function(){var e=o.get("$http");r.config.attempt?r.config.attempt++:r.config.attempt=1,e(r.config).then(function(e){i.resolve(e)},function(e){i.reject(e)}).finally(function(){n(s.remove,1e3)})},2e3)}),document.body.appendChild(s[0]),i.promise}function t(n,o,r,i){return{response:function(e){var t;return e&&/^application\/json/.test(e.config.headers.Accept)&&/^[\n\r\t ]*<!DOCTYPE html/.test(e.data)?n.usesCASAuthentication||n.usesSAML2Authentication?a(n,o,r,i,e):(t=i.get("$state"),angular.element(n).off("beforeunload"),t.href(t.current)?n.location.href=n.ApplicationBaseURL+t.href(t.current):n.location.href=n.ApplicationBaseURL,o.reject()):e}}}function n(n,o,r,i,s){return{responseError:function(e){var t;if(/^application\/json/.test(e.config.headers.Accept)){if((o.usesCASAuthentication||o.usesSAML2Authentication)&&(-1==e.status||500==e.status&&-1!==document.cookie.indexOf("cas-location")))return a(o,r,i,s,e);o.usesSAML2Authentication&&401==e.status&&!o.recovered?(t=s.get("$state"),angular.element(o).off("beforeunload"),o.recovered=!0,o.location.href=o.ApplicationBaseURL+t.href(t.current)):e.data&&e.data.quiet||n.$broadcast("http:Error",e)}return r.reject(e)}}}angular.Line truncated
function l(){var n,e,t=arguments[0],o=t,r=arguments;for(labels[t]?o=labels[t]:clabels[t]&&(o=clabels[t]),n=1,e=0;n<r.length;n++,e++)o=o.replace("%{"+e+"}",r[n]);return o=(n=1)<r.length?o.replace(/%((%)|s|d)/g,function(e){var t=null;return e[2]?t=e[2]:(t=r[n],"%d"===e&&(t=parseFloat(t),isNaN(t))&&(t=0),n++),t}):o}function hexToRgb(e){e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:null}function contrast(e){var t=1,e=hexToRgb(e);if(e){for(var n=[e.r/255,e.g/255,e.b/255],o=0;o<n.length;++o)n[o]=n[o]<=.03928?n[o]/12.92:Math.pow((n[o]+.055)/1.055,2.4);t=.2126*n[0]+.7152*n[1]+.0722*n[2]}return.179<t?"black":"white"}function guid(){function e(){return(65536*(1+Math.random())|0).toString(16).substring(1)}return(e()+e()+"-"+e()+"-4"+e().substr(0,3)+"-"+e()+"-"+e()+e()+e()).toLowerCase()}!function(){"use strict";function e(e,t,n,o,r,i,s){e.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/),r.definePalette("sogo-green",{50:"eaf5e9",100:"cbe5c8",200:"aad6a5",300:"88c781",400:"66b86a",500:"56b04c",600:"4da143",700:"388e3c",800:"367d2e",900:"225e1b",A100:"fafafa",A200:"69f0ae",A400:"00e676",A700:"00c853",contrastDefaultColor:"dark",contrastLightColors:["300","400","500","600","700","800","900"]}),r.definePalette("sogo-blue",{50:"f0faf9",100:"e1f5f3",200:"ceebe8",300:"bfe0dd",400:"b2d6d3",500:"a1ccc8",600:"8ebfbb",700:"7db3b0",800:"639997",900:"4d8080",A100:"d4f7fa",A200:"c3f5fa",A400:"53e3f0",A700:"00b0c0",contrastDefaultColor:"light",contrastDarkColors:["50","100","200"]});e=r.extendPalette("grey",{1e3:"baa870"});r.definePalette("sogo-grey",e),r.theme("default").primaryPalette("sogo-blue",{default:"900","hue-1":"400","hue-2":"800","hue-3":"A700"}).accentPalette("sogo-green",{default:"500","hue-1":"A100","hue-2":"300","hue-3":"A700"}).backgroundPalette("sogo-grey"),r.registerStyles(["md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent,","md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-input-container[md-no-float] .md-input {"," background-color: '{{accent-hue-1}}';"," color: '{{foreground-1}}';","}","md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-icon {"," color: '{{foreground-1}}';"," fill: '{{foreground-1}}';","}"].join("")),r.registerStyles([".md-autocomplete-suggestions.md-3-line li p {"," color: '{{foreground-2}}';","}"].join("")),r.registerStyles([".sg-time-selection-indicator.sg-time-selected,",".sg-time-selection-indicator:hover.sg-time-selected,",".sg-time-selection-indicator.md-focus.sg-time-selected {"," background: '{{primary-500}}';","}",".sg-timepicker-open .sg-timepicker-icon {"," color: '{{primary-900}}';","}",".sg-timepicker-time,",".sg-timepicker-open .sg-timepicker-input-container {"," background: '{{background-hue-1}}';","}",".sg-timepicker-input-mask-opaque {"," box-shadow: 0 0 0 9999px '{{background-hue-1}}';","}"].join("")),r.registerStyles(["[ui-view=calendars] .hours {"," color: '{{primary-700}}';","}",".attendees .busy {"," background-color: '{{background-1000}}';","}",".attendees .event {"," background-color: '{{primary-300}}';","}"].join("")),r.registerStyles([".sg-message-thread {"," background-color: '{{primary-100}}';","}",".sg-message-thread-first {"," background-color: '{{primary-200}}';","}"].join("")),window.DebugEnabled||(t.debugEnabled(!1),n.debugInfoEnabled(!1),i.disableWarnings(),s.errorOnUnhandledRejections(!1),r.generateThemesOnDemand(!0)),o.interceptors.push("AuthInterceptor"),o.interceptors.push("ErrorInterceptor")}function a(t,e,n,o,r){var i=e.defer(),s=angular.element('<iframe class="ng-hide" src="'+t.UserFolderURL+'recover"></iframe>');return s.on("load",function(){var e=o.get("$state");2<r.config.attempt?(angular.element(t).off("beforeunload"),t.location.href=t.ApplicationBaseURL+e.href(e.current),i.reject()):n(function(){var e=o.get("$http");r.config.attempt?r.config.attempt++:r.config.attempt=1,e(r.config).then(function(e){i.resolve(e)},function(e){i.reject(e)}).finally(function(){n(s.remove,1e3)})},2e3)}),document.body.appendChild(s[0]),i.promise}function t(n,o,r,i){return{response:function(e){var t;return e&&/^application\/json/.test(e.config.headers.Accept)&&/^[\n\r\t ]*<!DOCTYPE html/.test(e.data)?n.usesCASAuthentication||n.usesSAML2Authentication?a(n,o,r,i,e):(t=i.get("$state"),angular.element(n).off("beforeunload"),t.href(t.current)?n.location.href=n.ApplicationBaseURL+t.href(t.current):n.location.href=n.ApplicationBaseURL,o.reject()):e}}}function n(n,o,r,i,s){return{responseError:function(e){var t;if(/^application\/json/.test(e.config.headers.Accept)){if((o.usesCASAuthentication||o.usesSAML2Authentication)&&(-1==e.status||500==e.status&&-1!==document.cookie.indexOf("cas-location")))return a(o,r,i,s,e);o.usesSAML2Authentication&&401==e.status&&!o.recovered?(t=s.get("$state"),angular.element(o).off("beforeunload"),o.recovered=!0,o.location.href=o.ApplicationBaseURL+t.href(t.current)):e.data&&e.data.quiet||n.$broadcast("http:Error",e)}return r.reject(e)}}}angular.Line truncated
//# sourceMappingURL=Common.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"Common.js","sources":["Common/utils.js","Common/Common.app.js","Common/mdColors.app.js","Common/cssescape.filter.js","Common/decodeUri.filter.js","Common/encodeUri.filter.js","Common/ensureTarget.filter.js","Common/loc.filter.js","Common/range.filter.js","Common/txt2html.filter.js","Common/AclController.js","Common/navController.js","Common/Acl.service.js","Common/Authentication.service.js","Common/Dialog.service.js","Common/Gravatar.service.js","Common/Resource.service.js","Common/sgFocus.service.js","Common/sgHotkeys.service.js","Common/sgRippleClick.service.js","Common/User.service.js","Common/sgAutogrow.directive.js","Common/sgAvatarImage.directive.js","Common/sgBlockToggle.directive.js","Common/sgCheckmark.directive.js","Common/sgColorPicker.directive.js","Common/sgCompile.directive.js","Common/sgDatepickerReadonlyInput.directive.js","Common/sgDraggable.directive.js","Common/sgDroppable.directive.js","Common/sgEnter.directive.js","Common/sgEscape.directive.js","Common/sgFocus.directive.js","Common/sgFolderStylesheet.directive.js","Common/sgLabels.directive.js","Common/sgNoDirtyCheck.directive.js","Common/sgPlaceholder.directive.js","Common/sgQrCode.directive.js","Common/sgResetOnDisabled.directive.js","Common/sgRippleClick.directive.js","Common/sgSearch.directive.js","Common/sgSelectOnly.directive.js","Common/sgSubscribe.directive.js","Common/sgTimepicker.directive.js","Common/sgToggleGrid.directive.js"],"names":["l","i","j","key","arguments","value","args","labels","clabels","length","replace","m","val","parseFloat","isNaN","hexToRgb","hex","result","exec","r","parseInt","g","b","contrast","color","c","Math","pow","guid","S4","random","toString","substring","substr","toLowerCase","configure","$animateProvider","$logProvider","$compileProvider","$httpProvider","$mdThemingProvider","$mdAriaProvider","$qProvider","classNameFilter","definePalette","50","100","200","300","400","500","600","700","800","900","A100","A200","A400","A700","contrastDefaultColor","contrastLightColors","contrastDarkColors","greyMap","extendPalette","1000","theme","primaryPalette","default","hue-1","hue-2","hue-3","accentPalette","backgroundPalette","registerStyles","join","window","DebugEnabled","debugEnabled","debugInfoEnabled","disableWarnings","errorOnUnhandledRejections","generateThemesOnDemand","interceptors","push","renewTicket","$window","$q","$timeout","$injector","response","deferred","defer","iframe","angular","element","UserFolderURL","on","$state","get","config","attempt","off","location","href","ApplicationBaseURL","current","reject","$http","then","resolve","finally","remove","document","body","appendChild","promise","AuthInterceptor","test","headers","Accept","data","usesCASAuthentication","usesSAML2Authentication","ErrorInterceptor","$rootScope","responseError","rejection","status","cookie","indexOf","recovered","quiet","$broadcast","module","isPopup","classList","contains","baseURL","resourcesURL","ResourcesURL","activeUser","param","settings","login","UserLogin","identification","UserIdentification","email","UserEmail","language","UserLanguage","folderURL","isSuperUser","IsSuperUser","path","calendar","UserCalendarPath","contacts","UserContactsPath","mail","UserMailPath","preferences","UserPreferencesPath","administration","UserAdministrationPath","help","HelpURL","logoff","UserLogoffPath","minimumSearchLength","isNumber","constant","selection","xs","gt-xs","sm","gt-sm","md","gt-md","lg","gt-lg","xl","print","toastPosition","factory","$inject","_$mdThemingProvider","runBlock","$interpolate","$document","$log","buildCssSelectors","selectors","fgDefault","bgDefault","bdrDefault","fgDefaultHue","bgDefaultHue","fgColor","bgColor","bdrColor","fgHue","bgHue","customSheet","style","head","querySelector","createElement","title","createTextNode","sheet","index","cssRules","deleteRule","addRule","fgInterpolate","bgInterpolate","themeName","paletteName","colorArray","hueName","context","palette","hue","insertRule","addBorderRule","bdrInterpolate","colorValue","forEach","_THEMES","_PALETTES","colors","primary","name","hues","run","cssEscape","CSS","escape","filter","decodeUri","decodeURIComponent","encodeUri","encodeURIComponent","ensureTarget","$sce","tree","find","attr","trustAs","html","n","res","txt2html","linkyFilter","text","String","rel","undefined","AclController","$mdDialog","Dialog","usersWithACL","User","folder","vm","this","selectUser","user","$event","target","parentNode","selectedUid","uid","selectedUser","inactive","$rights","users","userToAdd","searchText","folderClassName","isFunction","getClassName","templateName","getElementById","$isAnonymous","userFilter","$query","$filter","$acl","dry","closeModal","$resetUsersRights","hide","saveModal","$saveUsersRights","alert","confirmChange","confirmation","$confirmRights","showing","message","removeUser","$removeUser","addUser","$addUser","toggleAllRights","$toggleAllRights","hasNoRight","$hasNoRight","showRights","controller","navController",Line truncated
{"version":3,"file":"Common.js","sources":["Common/utils.js","Common/Common.app.js","Common/mdColors.app.js","Common/cssescape.filter.js","Common/decodeUri.filter.js","Common/encodeUri.filter.js","Common/ensureTarget.filter.js","Common/loc.filter.js","Common/range.filter.js","Common/txt2html.filter.js","Common/AclController.js","Common/navController.js","Common/Acl.service.js","Common/Authentication.service.js","Common/Dialog.service.js","Common/Gravatar.service.js","Common/Resource.service.js","Common/sgFocus.service.js","Common/sgHotkeys.service.js","Common/sgRippleClick.service.js","Common/User.service.js","Common/sgAutogrow.directive.js","Common/sgAvatarImage.directive.js","Common/sgBlockToggle.directive.js","Common/sgCheckmark.directive.js","Common/sgColorPicker.directive.js","Common/sgCompile.directive.js","Common/sgDatepickerReadonlyInput.directive.js","Common/sgDraggable.directive.js","Common/sgDroppable.directive.js","Common/sgEnter.directive.js","Common/sgEscape.directive.js","Common/sgFocus.directive.js","Common/sgFolderStylesheet.directive.js","Common/sgLabels.directive.js","Common/sgNoDirtyCheck.directive.js","Common/sgPlaceholder.directive.js","Common/sgQrCode.directive.js","Common/sgResetOnDisabled.directive.js","Common/sgRippleClick.directive.js","Common/sgSearch.directive.js","Common/sgSelectOnly.directive.js","Common/sgSubscribe.directive.js","Common/sgTimepicker.directive.js","Common/sgToggleGrid.directive.js"],"names":["l","i","j","key","arguments","value","args","labels","clabels","length","replace","m","val","parseFloat","isNaN","hexToRgb","hex","result","exec","r","parseInt","g","b","contrast","color","c","Math","pow","guid","S4","random","toString","substring","substr","toLowerCase","configure","$animateProvider","$logProvider","$compileProvider","$httpProvider","$mdThemingProvider","$mdAriaProvider","$qProvider","classNameFilter","definePalette","50","100","200","300","400","500","600","700","800","900","A100","A200","A400","A700","contrastDefaultColor","contrastLightColors","contrastDarkColors","greyMap","extendPalette","1000","theme","primaryPalette","default","hue-1","hue-2","hue-3","accentPalette","backgroundPalette","registerStyles","join","window","DebugEnabled","debugEnabled","debugInfoEnabled","disableWarnings","errorOnUnhandledRejections","generateThemesOnDemand","interceptors","push","renewTicket","$window","$q","$timeout","$injector","response","deferred","defer","iframe","angular","element","UserFolderURL","on","$state","get","config","attempt","off","location","href","ApplicationBaseURL","current","reject","$http","then","resolve","finally","remove","document","body","appendChild","promise","AuthInterceptor","test","headers","Accept","data","usesCASAuthentication","usesSAML2Authentication","ErrorInterceptor","$rootScope","responseError","rejection","status","cookie","indexOf","recovered","quiet","$broadcast","module","isPopup","classList","contains","baseURL","resourcesURL","ResourcesURL","activeUser","param","settings","login","UserLogin","identification","UserIdentification","email","UserEmail","language","UserLanguage","folderURL","isSuperUser","IsSuperUser","path","calendar","UserCalendarPath","contacts","UserContactsPath","mail","UserMailPath","preferences","UserPreferencesPath","administration","UserAdministrationPath","help","HelpURL","logoff","UserLogoffPath","minimumSearchLength","isNumber","constant","selection","xs","gt-xs","sm","gt-sm","md","gt-md","lg","gt-lg","xl","print","toastPosition","factory","$inject","_$mdThemingProvider","runBlock","$interpolate","$document","$log","buildCssSelectors","selectors","fgDefault","bgDefault","bdrDefault","fgDefaultHue","bgDefaultHue","fgColor","bgColor","bdrColor","fgHue","bgHue","customSheet","style","head","querySelector","createElement","title","createTextNode","sheet","index","cssRules","deleteRule","addRule","fgInterpolate","bgInterpolate","themeName","paletteName","colorArray","hueName","context","palette","hue","insertRule","addBorderRule","bdrInterpolate","colorValue","forEach","_THEMES","_PALETTES","colors","primary","name","hues","run","cssEscape","CSS","escape","filter","decodeUri","decodeURIComponent","encodeUri","encodeURIComponent","ensureTarget","$sce","tree","find","attr","trustAs","html","n","res","txt2html","linkyFilter","text","String","rel","undefined","AclController","$mdDialog","Dialog","usersWithACL","User","folder","vm","this","selectUser","user","$event","target","parentNode","selectedUid","uid","selectedUser","inactive","$rights","users","userToAdd","searchText","folderClassName","isFunction","getClassName","templateName","getElementById","$isAnonymous","userFilter","$query","$filter","$acl","dry","closeModal","$resetUsersRights","hide","saveModal","$saveUsersRights","alert","confirmChange","confirmation","$confirmRights","showing","message","removeUser","$removeUser","addUser","$addUser","toggleAllRights","$toggleAllRights","hasNoRight","$hasNoRight","showRights","controller","navController",Line truncated
@@ -170,45 +170,6 @@
return d.promise;
}, // login: function(data) { ...
loginName: function(data) {
var d = $q.defer(),
username = data.username,
language;
if (data.language && data.language != 'WONoSelectionString') {
language = data.language;
}
$http({
method: 'POST',
url: '/SOGo/connectName?userName='+username,
// data: JSON.stringify({userName: username}),
data: {userName: username},
// headers: {
// //'Content-Type': undefined
// //'Content-Type': "application/x-www-form-urlencoded"
// 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8'
// }
}).then(function(response) {
var data = response.data;
// Make sure browser's cookies are enabled
if (navigator && !navigator.cookieEnabled) {
d.reject({error: l('cookiesNotEnabled')});
}
else {
if(data.redirect) {
//Redirection in case of openID
d.resolve({ url: data.redirect });
}
}
}, function(error) {
var response, perr, data = error.data;
d.reject(response);
});
return d.promise;
},
changePassword: function(userName, domain, newPassword, oldPassword, token) {
var d = $q.defer(),
xsrfCookie = $cookies.get('XSRF-TOKEN');
+1 -1
View File
@@ -1,2 +1,2 @@
!function(){"use strict";function c(e){var t=this;"function"!=typeof e.then&&(angular.extend(this,e),_.forEach(this.identities,function(e){var t;e.fullName&&e.email?e.full=e.fullName+" <"+e.email+">":e.email?e.full="<"+e.email+">":e.full="",e.signature&&(t=angular.element("<div>"+e.signature+"</div>"),e.textSignature=_.map(t.contents(),"textContent").join(" ").trim())}),this.$mailboxes)&&c.$Mailbox.$unwrapCollection(this,c.$q.when({mailboxes:this.$mailboxes})).then(function(e){t.$mailboxes=e})}c.$factory=["$q","$timeout","$log","sgSettings","Resource","Preferences","Mailbox","Message",function(e,t,s,n,i,a,o,r){return angular.extend(c,{$q:e,$timeout:t,$log:s,$$resource:new i(n.activeUser("folderURL")+"Mail",n.activeUser()),$Preferences:a,$Mailbox:o,$Message:r}),c}];try{angular.module("SOGo.MailerUI")}catch(e){angular.module("SOGo.MailerUI",["SOGo.Common"])}angular.module("SOGo.MailerUI").factory("Account",c.$factory),c.$findAll=function(e){return e?c.$unwrapCollection(e):c.$accounts?c.$q.when(c.$accounts):c.$$resource.fetch("","mailAccounts").then(function(e){return c.$unwrapCollection(e)})},c.$unwrapCollection=function(e){var s=[];return angular.forEach(e,function(e,t){e.id=t,s[t]=new c(e)}),c.$accounts=s},c.refreshUnseenCount=function(e){var t,s=1===c.$Preferences.defaults.SOGoMailFetchAllUnseenCountFolders,n=c.$Preferences.defaults.SOGoRefreshViewCheck;if(s)t=[];else{if(!e)throw Error("SOGoMailFetchAllUnseenCountFolders is disabled and no folders list provided");t=e}_.forEach(c.$accounts,function(e){s?_.forEach(e.$$flattenMailboxes,function(e){t.push(e.id)}):(_.includes(t,e.id+"/folderINBOX")||t.push(e.id+"/folderINBOX"),_.forEach(e.$$flattenMailboxes,function(e){angular.isDefined(e.unseenCount)&&!_.includes(t,e.id)&&t.push(e.id)}))}),c.$$resource.post("","unseenCount",{mailboxes:t}).then(function(t){_.forEach(c.$accounts,function(e){_.forEach(e.$$flattenMailboxes,function(e){angular.isDefined(t[e.id])&&(e.unseenCount=t[e.id])})})}),n&&"manually"!=n&&(c.$refreshUnseenCount&&c.$timeout.cancel(c.$refreshUnseenCount),c.$refreshUnseenCount=c.$timeout(angular.bind(this,c.refreshUnseenCount,e),1e3*n.timeInterval()))},c.prototype.getLength=function(){return this.$expanded?this.$flattenMailboxes().length:0},c.prototype.getItemAtIndex=function(e){var t=this.$flattenMailboxes();return 0<=e&&e<t.length?t[e]:null},c.prototype.$getMailboxes=function(e){var a=this,t=e&&e.reload;return this.$mailboxes&&!t?c.$q.when(this.$mailboxes):(!t&&this.$futureMailboxesData||(this.$futureMailboxesData=c.$Mailbox.$find(this,e).then(function(e){function s(e){_.forEach(e,function(e){var t=_.find(n,["id",e.id]);t&&(e.unseenCount=t.unseenCount),e.children&&0<e.children.length&&s(e.children)})}var n=a.$flattenMailboxes({all:!0});a.$mailboxes=e,a.$expanded=!1;s(a.$mailboxes);function t(e){_.forEach(e,function(e){e.$expanded=0<=i.indexOf("/"+e.id),e.children&&0<e.children.length&&t(e.children)})}var i;if(c.$Preferences.settings.Mail.ExpandedFolders){if(angular.isString(c.$Preferences.settings.Mail.ExpandedFolders))try{i=angular.fromJson(c.$Preferences.settings.Mail.ExpandedFolders)}catch(e){c.$log.warn("Can't parse list of expanded folders. String was: "+c.$Preferences.settings.Mail.ExpandedFolders),i=[]}else i=c.$Preferences.settings.Mail.ExpandedFolders;a.$expanded=0<=i.indexOf("/"+a.id),0<i.length&&t(a.$mailboxes)}return c.$accounts&&(a.$expanded|=1==c.$accounts.length),a.$flattenMailboxes({reload:!0}),a.$mailboxes})),this.$futureMailboxesData)},c.prototype.$flattenMailboxes=function(t){function s(e){_.forEach(e,function(e){n.push(e),(t&&t.all||e.$expanded)&&e.children&&0<e.children.length&&s(e.children)})}var n=[],i=[];return!this.$$flattenMailboxes||t&&(t.reload||t.all)?(s(this.$mailboxes),t&&t.all||(this.$$flattenMailboxes=n,t&&t.saveState&&(_.forEach(c.$accounts,function(e){e.$expanded&&i.push("/"+e.id),_.reduce(e.$$flattenMailboxes,function(e,t){return t.$expanded&&e.push("/"+t.id),e},i)}),c.$$resource.post(null,"saveFoldersState",i)))):n=this.$$flattenMailboxes,n},c.prototype.$getMailboxByType=function(s){function n(e){var t=_.find(e,function(e){return e.type==s});return t||angular.forEach(e,function(e){!t&&e.children&&0<e.children.length&&(t=n(e.children))}),t}return n(this.$mailboxes)},c.prototype.$getMailboxByPath=function(s){function n(e){var t=_.find(e,function(e){return e.path==s});return t||angular.forEach(e,function(e){!t&&e.children&&0<e.children.length&&(t=n(e.children))}),t}var e;if(null==(e=n(this.$mailboxes)))throw Error("No mailbox found matching path "+s);return e},c.prototype.$newMailbox=function(e,t){var s=this;return c.$$resource.post(e.toString(),"createFolder",{name:t}).then(function(){s.$getMailboxes({reload:!0})})},c.prototype.getTextSignature=function(e){var t;return e.signature?(t=angular.element("<div>"+e.signature+"</div>"),e.textSignature=_.map(t.contents(),"textContent").join(" ").trim()):e.textSignature="",e.textSignature},c.prototype.$hasCertificate=function(){return this.security&&this.security.hasCLine truncated
!function(){"use strict";function c(e){var t=this;"function"!=typeof e.then&&(angular.extend(this,e),_.forEach(this.identities,function(e){var t;e.fullName&&e.email?e.full=e.fullName+" <"+e.email+">":e.email?e.full="<"+e.email+">":e.full="",e.signature&&(t=angular.element("<div>"+e.signature+"</div>"),e.textSignature=_.map(t.contents(),"textContent").join(" ").trim())}),this.$mailboxes)&&c.$Mailbox.$unwrapCollection(this,c.$q.when({mailboxes:this.$mailboxes})).then(function(e){t.$mailboxes=e})}c.$factory=["$q","$timeout","$log","sgSettings","Resource","Preferences","Mailbox","Message",function(e,t,s,n,i,a,o,r){return angular.extend(c,{$q:e,$timeout:t,$log:s,$$resource:new i(n.activeUser("folderURL")+"Mail",n.activeUser()),$Preferences:a,$Mailbox:o,$Message:r}),c}];try{angular.module("SOGo.MailerUI")}catch(e){angular.module("SOGo.MailerUI",["SOGo.Common"])}angular.module("SOGo.MailerUI").factory("Account",c.$factory),c.$findAll=function(e){return e?c.$unwrapCollection(e):c.$accounts?c.$q.when(c.$accounts):c.$$resource.fetch("","mailAccounts").then(function(e){return c.$unwrapCollection(e)})},c.$unwrapCollection=function(e){var s=[];return angular.forEach(e,function(e,t){e.id=t,s[t]=new c(e)}),c.$accounts=s},c.refreshUnseenCount=function(e){var t,s=1===c.$Preferences.defaults.SOGoMailFetchAllUnseenCountFolders,n=c.$Preferences.defaults.SOGoRefreshViewCheck;if(s)t=[];else{if(!e)throw Error("SOGoMailFetchAllUnseenCountFolders is disabled and no folders list provided");t=e}_.forEach(c.$accounts,function(e){s?_.forEach(e.$$flattenMailboxes,function(e){t.push(e.id)}):(_.includes(t,e.id+"/folderINBOX")||t.push(e.id+"/folderINBOX"),_.forEach(e.$$flattenMailboxes,function(e){angular.isDefined(e.unseenCount)&&!_.includes(t,e.id)&&t.push(e.id)}))}),c.$$resource.post("","unseenCount",{mailboxes:t}).then(function(t){_.forEach(c.$accounts,function(e){_.forEach(e.$$flattenMailboxes,function(e){angular.isDefined(t[e.id])&&(e.unseenCount=t[e.id])})})}),n&&"manually"!=n&&(c.$refreshUnseenCount&&c.$timeout.cancel(c.$refreshUnseenCount),c.$refreshUnseenCount=c.$timeout(angular.bind(this,c.refreshUnseenCount,e),1e3*n.timeInterval()))},c.prototype.getLength=function(){return this.$expanded?this.$flattenMailboxes().length:0},c.prototype.getItemAtIndex=function(e){var t=this.$flattenMailboxes();return 0<=e&&e<t.length?t[e]:null},c.prototype.$getMailboxes=function(e){var a=this,t=e&&e.reload;return this.$mailboxes&&!t?c.$q.when(this.$mailboxes):(!t&&this.$futureMailboxesData||(this.$futureMailboxesData=c.$Mailbox.$find(this,e).then(function(e){function s(e){_.forEach(e,function(e){var t=_.find(n,["id",e.id]);t&&(e.unseenCount=t.unseenCount),e.children&&0<e.children.length&&s(e.children)})}var n=a.$flattenMailboxes({all:!0});a.$mailboxes=e,a.$expanded=!1;s(a.$mailboxes);function t(e){_.forEach(e,function(e){e.$expanded=0<=i.indexOf("/"+e.id),e.children&&0<e.children.length&&t(e.children)})}var i;if(c.$Preferences.settings.Mail.ExpandedFolders){if(angular.isString(c.$Preferences.settings.Mail.ExpandedFolders))try{i=angular.fromJson(c.$Preferences.settings.Mail.ExpandedFolders)}catch(e){c.$log.warn("Can't parse list of expanded folders. String was: "+c.$Preferences.settings.Mail.ExpandedFolders),i=[]}else i=c.$Preferences.settings.Mail.ExpandedFolders;a.$expanded=0<=i.indexOf("/"+a.id),0<i.length&&t(a.$mailboxes)}return c.$accounts&&(a.$expanded|=1==c.$accounts.length),a.$flattenMailboxes({reload:!0}),a.$mailboxes})),this.$futureMailboxesData)},c.prototype.$flattenMailboxes=function(t){function s(e){_.forEach(e,function(e){n.push(e),(t&&t.all||e.$expanded)&&e.children&&0<e.children.length&&s(e.children)})}var n=[],i=[];return!this.$$flattenMailboxes||t&&(t.reload||t.all)?(s(this.$mailboxes),t&&t.all||(this.$$flattenMailboxes=n,t&&t.saveState&&(_.forEach(c.$accounts,function(e){e.$expanded&&i.push("/"+e.id),_.reduce(e.$$flattenMailboxes,function(e,t){return t.$expanded&&e.push("/"+t.id),e},i)}),c.$$resource.post(null,"saveFoldersState",i)))):n=this.$$flattenMailboxes,n},c.prototype.$getMailboxByType=function(s){function n(e){var t=_.find(e,function(e){return e.type==s});return t||angular.forEach(e,function(e){!t&&e.children&&0<e.children.length&&(t=n(e.children))}),t}return n(this.$mailboxes)},c.prototype.$getMailboxByPath=function(s){function n(e){var t=_.find(e,function(e){return e.path==s});return t||angular.forEach(e,function(e){!t&&e.children&&0<e.children.length&&(t=n(e.children))}),t}var e;if(null==(e=n(this.$mailboxes)))throw Error("No mailbox found matching path "+s);return e},c.prototype.$newMailbox=function(e,t){var s=this;return c.$$resource.post(e.toString(),"createFolder",{name:t}).then(function(){s.$getMailboxes({reload:!0})})},c.prototype.getTextSignature=function(e){var t;return e.signature?(t=angular.element("<div>"+e.signature+"</div>"),e.textSignature=_.map(t.contents(),"textContent").join(" ").trim()):e.textSignature="",e.textSignature},c.prototype.$hasCertificate=function(){return this.security&&this.security.hasCLine truncated
//# sourceMappingURL=Mailer.services.js.map
@@ -1 +1 @@
{"version":3,"file":"Mailer.services.js","sources":["Mailer/Account.service.js","Mailer/Mailbox.service.js","Mailer/Message.service.js","Mailer/sgImageGallery.service.js","Mailer/VirtualMailbox.service.js","Mailer/MailboxController.js","Mailer/MailboxesController.js","Mailer/MessageController.js","Mailer/MessageEditorController.js","Mailer/sgAccountSection.directive.js","Mailer/sgIMIP.directive.js","Mailer/sgMailboxListItem.directive.js","Mailer/sgMessageListItem.directive.js","Mailer/sgMessageListItemMain.directive.js","Mailer/sgZoomableImage.directive.js"],"names":["Account","futureAccountData","_this","this","then","angular","extend","_","forEach","identities","identity","element","fullName","email","full","signature","textSignature","map","contents","join","trim","$mailboxes","$Mailbox","$unwrapCollection","$q","when","mailboxes","collection","$factory","$timeout","$log","Settings","Resource","Preferences","Mailbox","Message","$$resource","activeUser","$Preferences","$Message","module","e","factory","$findAll","data","$accounts","fetch","o","i","id","refreshUnseenCount","folders","unseenCountFolders","fetchAllUnseenCountFolders","defaults","SOGoMailFetchAllUnseenCountFolders","refreshViewCheck","SOGoRefreshViewCheck","Error","account","$$flattenMailboxes","mailbox","push","includes","isDefined","unseenCount","post","$refreshUnseenCount","cancel","bind","timeInterval","prototype","getLength","$expanded","$flattenMailboxes","length","getItemAtIndex","index","expandedMailboxes","$getMailboxes","options","reload","$futureMailboxesData","$find","_visitForUnseencount","previousMailbox","find","previousMailboxes","children","all","_visitForExpanded","expandedFolders","indexOf","settings","Mail","ExpandedFolders","isString","fromJson","warn","_visit","allMailboxes","saveState","reduce","$getMailboxByType","type","_find","$getMailboxByPath","path","$newMailbox","name","toString","getTextSignature","$hasCertificate","security","hasCertificate","$certificate","$$certificate","reject","$removeCertificate","updateQuota","percent","description","maxQuota","Math","round","usedSpace","l","formatted","maxMessages","messagesCount","$quota","$newMessage","debug","JSON","stringify","undefined","accountId","mailboxPath","message","$absolutePath","asDraft","accountDefaults","AuxiliaryMailAccounts","alwaysSign","sign","alwaysEncrypt","encrypt","editable","isNew","mailto","isObject","$parseMailto","$addDelegate","user","deferred","defer","param","uid","delegates","resolve","users","status","promise","$removeDelegate","splice","$omit","deep","defaultIdentity","value","key","copy","isReadOnly","pick","isDefault","forceDefaultIdentity","futureMailboxData","$account","init","newMailboxData","create","$unwrap","$rootScope","Acl","PRELOAD","BATCH_DELETE_LIMIT","$$Acl","$query","sort","asc","selectedFolder","$refreshTimeout","$virtualMode","$virtualPath","$searchMode","SortingState","parseInt","constant","LOOKAHEAD","SIZE","createMailboxes","level","isSentFolder","isDraftsFolder","quotas","split","component","asCSSIdentifier","isUndefined","uidsMap","headers","$isLoading","$messages","$visibleMessages","$selectedMessages","$highlightWords","$id","$acl","threaded","$collapsedThreads","threadsCollapsed","$displayName","$isEditable","isEditable","$isSpecial","$icon","$isNoInferiors","isNoInferiors","$shadowData","selectFolder","setSearchMode","searchMode","$lastVisibleIndex","max","$loadMessage","selectedMessages","updateCache","filter","selected","selectedCount","$unselectMessages","isSelectedMessage","messageId","$selectedMessage","selectedMessage","$selectedMessageIndex","hasSelectedMessage","$filter","sortingAttributes","filters","action","labels","searchBy","searchInput","word","cleanedWord","toLowerCase","match","secondFilter","$flaggedOnly","$unseenOnly","$syncToken","syncToken","unseenOnly","flaggedOnly","keys","$filteredLabels","k","f","endIndex","uids","startIndex","loaded","subject","min","loading","futureHeadersData","$unwrapHeaders","flags","isNoSelect","isWritable","getClassName","base","$rename","findParent","parent","parentMailbox","$save","_updateChildren","child","replace","pathRE","oldPath","sibling","localeCompare","RegExp","$compact","$canFolderAs","$setFolderAs","$empty","capitalize","substring","$markAsRead","isread","getLabels","$labels","filteredByLabel","$flagMessages","messages","operation","msgUIDs","forwardMessages","saveSelectedMessages","selectedUIDs","download","exportFolder","filename","open","$delete","$_deleteMessages","firstIndex","forEachRight","selectedIndex","findIndex","updateVisibleMessages","$deleteMessages","batchSize","_deleteMessages","start","end","currentUids","slice","$markOrUnMarkMessagesAsJunk","method","$copyMessages","folder","$moveMessages","$move","parentPath","finally","save","response","error","$reset","Object","assign","childrenArray","collapsedThread","msg","first","collapsed","$broadcast","$futureMailboxData","headersFields","msgObject","hasNewMessages","$topIndex","deleted","jLine truncated
{"version":3,"file":"Mailer.services.js","sources":["Mailer/Account.service.js","Mailer/Mailbox.service.js","Mailer/Message.service.js","Mailer/sgImageGallery.service.js","Mailer/VirtualMailbox.service.js","Mailer/MailboxController.js","Mailer/MailboxesController.js","Mailer/MessageController.js","Mailer/MessageEditorController.js","Mailer/sgAccountSection.directive.js","Mailer/sgIMIP.directive.js","Mailer/sgMailboxListItem.directive.js","Mailer/sgMessageListItem.directive.js","Mailer/sgMessageListItemMain.directive.js","Mailer/sgZoomableImage.directive.js"],"names":["Account","futureAccountData","_this","this","then","angular","extend","_","forEach","identities","identity","element","fullName","email","full","signature","textSignature","map","contents","join","trim","$mailboxes","$Mailbox","$unwrapCollection","$q","when","mailboxes","collection","$factory","$timeout","$log","Settings","Resource","Preferences","Mailbox","Message","$$resource","activeUser","$Preferences","$Message","module","e","factory","$findAll","data","$accounts","fetch","o","i","id","refreshUnseenCount","folders","unseenCountFolders","fetchAllUnseenCountFolders","defaults","SOGoMailFetchAllUnseenCountFolders","refreshViewCheck","SOGoRefreshViewCheck","Error","account","$$flattenMailboxes","mailbox","push","includes","isDefined","unseenCount","post","$refreshUnseenCount","cancel","bind","timeInterval","prototype","getLength","$expanded","$flattenMailboxes","length","getItemAtIndex","index","expandedMailboxes","$getMailboxes","options","reload","$futureMailboxesData","$find","_visitForUnseencount","previousMailbox","find","previousMailboxes","children","all","_visitForExpanded","expandedFolders","indexOf","settings","Mail","ExpandedFolders","isString","fromJson","warn","_visit","allMailboxes","saveState","reduce","$getMailboxByType","type","_find","$getMailboxByPath","path","$newMailbox","name","toString","getTextSignature","$hasCertificate","security","hasCertificate","$certificate","$$certificate","reject","$removeCertificate","updateQuota","percent","description","maxQuota","Math","round","usedSpace","l","formatted","maxMessages","messagesCount","$quota","$newMessage","debug","JSON","stringify","undefined","accountId","mailboxPath","message","$absolutePath","asDraft","accountDefaults","AuxiliaryMailAccounts","alwaysSign","sign","alwaysEncrypt","encrypt","editable","isNew","mailto","isObject","$parseMailto","$addDelegate","user","deferred","defer","param","uid","delegates","resolve","users","status","promise","$removeDelegate","splice","$omit","deep","defaultIdentity","value","key","copy","isReadOnly","pick","isDefault","forceDefaultIdentity","futureMailboxData","$account","init","newMailboxData","create","$unwrap","$rootScope","Acl","PRELOAD","BATCH_DELETE_LIMIT","$$Acl","$query","sort","asc","selectedFolder","$refreshTimeout","$virtualMode","$virtualPath","$searchMode","SortingState","parseInt","constant","LOOKAHEAD","SIZE","createMailboxes","level","isSentFolder","isDraftsFolder","quotas","split","component","asCSSIdentifier","isUndefined","uidsMap","headers","$isLoading","$messages","$visibleMessages","$selectedMessages","$highlightWords","$id","$acl","threaded","$collapsedThreads","threadsCollapsed","$displayName","$isEditable","isEditable","$isSpecial","$icon","$isNoInferiors","isNoInferiors","$shadowData","selectFolder","setSearchMode","searchMode","$lastVisibleIndex","max","$loadMessage","selectedMessages","updateCache","filter","selected","selectedCount","$unselectMessages","isSelectedMessage","messageId","$selectedMessage","selectedMessage","$selectedMessageIndex","hasSelectedMessage","$filter","sortingAttributes","filters","action","labels","searchBy","searchInput","word","cleanedWord","toLowerCase","match","secondFilter","$flaggedOnly","$unseenOnly","$syncToken","syncToken","unseenOnly","flaggedOnly","keys","$filteredLabels","k","f","endIndex","uids","startIndex","loaded","subject","min","loading","futureHeadersData","$unwrapHeaders","flags","isNoSelect","isWritable","getClassName","base","$rename","findParent","parent","parentMailbox","$save","_updateChildren","child","replace","pathRE","oldPath","sibling","localeCompare","RegExp","$compact","$canFolderAs","$setFolderAs","$empty","capitalize","substring","$markAsRead","isread","getLabels","$labels","filteredByLabel","$flagMessages","messages","operation","msgUIDs","forwardMessages","saveSelectedMessages","selectedUIDs","download","exportFolder","filename","open","$delete","$_deleteMessages","firstIndex","forEachRight","selectedIndex","findIndex","updateVisibleMessages","$deleteMessages","batchSize","_deleteMessages","start","end","currentUids","slice","$markOrUnMarkMessagesAsJunk","method","$copyMessages","folder","$moveMessages","$move","parentPath","finally","save","response","error","$reset","Object","assign","childrenArray","collapsedThread","msg","first","collapsed","$broadcast","$futureMailboxData","headersFields","msgObject","hasNewMessages","$topIndex","deleted","jLine truncated
@@ -210,7 +210,9 @@
}
url = url.join('/');
popupWindow = $window.open(url, wId,
["resizable=1",
["width=680",
"height=520",
"resizable=1",
"scrollbars=1",
"toolbar=0",
"location=0",
+1 -1
View File
@@ -1,2 +1,2 @@
!function(){"use strict";angular.module("SOGo.MainUI",["SOGo.Common","SOGo.Authentication"]);function e(e,o,s,r,a,n,i,t){var d=this;this.$onInit=function(){this.creds={username:o.cookieUsername,password:null,domain:null,rememberLogin:angular.isDefined(o.cookieUsername)&&0<o.cookieUsername.length},o.loginHint&&(this.creds.username=o.loginHint),/\blanguage=/.test(o.location.search)&&(this.creds.language=o.language),this.loginState=!1,this.verificationCodePattern="\\d{6}",this.passwords={newPassword:null,newPasswordConfirmation:null,oldPassword:null,visible:!1},this.passwordRecovery={passwordRecoveryEnabled:!1,passwordRecoveryQuestionKey:null,passwordRecoveryQuestion:null,passwordRecoveryMode:null,passwordRecoveryQuestionAnswer:null,passwordRecoveryToken:null,passwordRecoveryLinkTimer:null,passwordRecoverySecondaryEmailText:null,passwordRecoveryMailDomain:null,showLoader:!1},this.showLogin=!1,s(function(){d.showLogin=!0;var e=window.location.search;let o=new URLSearchParams(e).get("token");0<window.location.pathname.indexOf("passwordRecoveryEmail")&&o?3===(e=(o=o.replace(/\//g,"")).split(".")).length&&(d.passwordRecovery.passwordRecoveryToken=o,e=JSON.parse(atob(e[1])),d.creds.username=e.username,d.creds.domain=e.domain,d.passwordRecovery.passwordRecoveryToken=o,d.passwordRecovery.passwordRecoveryMode="SecondaryEmail",d.passwordRecovery.passwordRecoveryEnabled=!0,d.loginState="passwordchange",d.showLogin=!1,t("loginContent")):d.retrievePasswordRecoveryEnabled(),0<document.querySelectorAll("*:autofill").length&&document.querySelectorAll("*:autofill").forEach(e=>{e.parentElement.classList.add("md-input-has-value")})},100)},this.login=function(){return d.loginState="authenticating",n.login(d.creds).then(function(e){e.totpmissingkey?(d.loginState="totpcode",i("totpcode")):e.totpdisabled?(d.loginState="totpdisabled",d.cn=e.cn,d.url=e.url):(d.loginState="logged",d.cn=e.cn,d.url=e.url,s(function(){d.continueLogin()},1e3))},function(e){var o,s;d.loginState="error",e.error?d.errorMessage=e.error:0<e.grace?(d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog.",e.grace)):0<e.expire?(s=86400<e.expire?(o=Math.round(e.expire/86400),l("days")):3600<e.expire?(o=Math.round(e.expire/3600),l("hours")):60<e.expire?(o=Math.round(e.expire/60),l("minutes")):(o=e.expire,l("seconds")),d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("Your password is going to expire in %{0} %{1}.",o,s)):e.passwordexpired&&(d.loginState="passwordchange",d.url=e.url)}),!1},this.loginName=function(){return d.loginState="authenticating",n.loginName(d.creds).then(function(e){d.loginState="logged",d.cn=e.cn,d.url=e.url,s(function(){d.continueLogin()},1e3)},function(e){var o,s;d.loginState="error",e.error?d.errorMessage=e.error:0<e.grace?(d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog.",e.grace)):0<e.expire?(s=86400<e.expire?(o=Math.round(e.expire/86400),l("days")):3600<e.expire?(o=Math.round(e.expire/3600),l("hours")):60<e.expire?(o=Math.round(e.expire/60),l("minutes")):(o=e.expire,l("seconds")),d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("Your password is going to expire in %{0} %{1}.",o,s)):e.passwordexpired&&(d.loginState="passwordchange",d.url=e.url)}),!1},this.restoreLogin=function(){d.showLogin=!1,"SecretQuestion"===d.passwordRecovery.passwordRecoveryMode?(t("loginContent"),d.passwordRecoveryInfo()):(delete d.creds.verificationCode,d.passwordRecoveryAbort())},this.continueLogin=function(){o.location.href===d.url?o.location.reload(!0):o.location.href=d.url},this.showAbout=function(e){function o(e){this.closeDialog=function(){e.hide()}}a.show({targetEvent:e,templateUrl:"aboutBox.html",controller:o,controllerAs:"about"}),o.$inject=["$mdDialog"]},this.changeLanguage=function(e){o.location.href=ApplicationBaseURL+"login?language="+this.creds.language},this.hello=function(e){return!1},this.canChangePassword=function(e){return this.passwords.newPasswordConfirmation&&this.passwords.newPasswordConfirmation.length&&this.passwords.newPassword!=this.passwords.newPasswordConfirmation?(e.newPasswordConfirmation.$setValidity("newPasswordMismatch",!1),!1):(e.newPasswordConfirmation.$setValidity("newPasswordMismatch",!0),!!(this.passwords.newPassword&&0<this.passwords.newPassword.length&&this.passwords.newPasswordConfirmation&&this.passwords.newPasswordConfirmation.length&&this.passwords.newPassword==this.passwords.newPasswordConfirmation&&(this.isInPasswordRecoveryMode()||!this.loginState&&this.passwords.oldPassword&&0<this.passwords.oldPassword.length||"passwordchange"==this.loginState&&this.passwords.oldPassword&&0<this.passwords.oldPassword.length)))},this.changePassword=function(){n.changePassword(this.creds.username,this.creds.domain,tLine truncated
!function(){"use strict";angular.module("SOGo.MainUI",["SOGo.Common","SOGo.Authentication"]);function e(e,o,s,r,a,n,i,t){var d=this;this.$onInit=function(){this.creds={username:o.cookieUsername,password:null,domain:null,rememberLogin:angular.isDefined(o.cookieUsername)&&0<o.cookieUsername.length},/\blanguage=/.test(o.location.search)&&(this.creds.language=o.language),this.loginState=!1,this.verificationCodePattern="\\d{6}",this.passwords={newPassword:null,newPasswordConfirmation:null,oldPassword:null,visible:!1},this.passwordRecovery={passwordRecoveryEnabled:!1,passwordRecoveryQuestionKey:null,passwordRecoveryQuestion:null,passwordRecoveryMode:null,passwordRecoveryQuestionAnswer:null,passwordRecoveryToken:null,passwordRecoveryLinkTimer:null,passwordRecoverySecondaryEmailText:null,passwordRecoveryMailDomain:null,showLoader:!1},this.showLogin=!1,s(function(){d.showLogin=!0;var e=window.location.search;let o=new URLSearchParams(e).get("token");0<window.location.pathname.indexOf("passwordRecoveryEmail")&&o?3===(e=(o=o.replace(/\//g,"")).split(".")).length&&(d.passwordRecovery.passwordRecoveryToken=o,e=JSON.parse(atob(e[1])),d.creds.username=e.username,d.creds.domain=e.domain,d.passwordRecovery.passwordRecoveryToken=o,d.passwordRecovery.passwordRecoveryMode="SecondaryEmail",d.passwordRecovery.passwordRecoveryEnabled=!0,d.loginState="passwordchange",d.showLogin=!1,t("loginContent")):d.retrievePasswordRecoveryEnabled(),0<document.querySelectorAll("*:autofill").length&&document.querySelectorAll("*:autofill").forEach(e=>{e.parentElement.classList.add("md-input-has-value")})},100)},this.login=function(){return d.loginState="authenticating",n.login(d.creds).then(function(e){e.totpmissingkey?(d.loginState="totpcode",i("totpcode")):e.totpdisabled?(d.loginState="totpdisabled",d.cn=e.cn,d.url=e.url):(d.loginState="logged",d.cn=e.cn,d.url=e.url,s(function(){d.continueLogin()},1e3))},function(e){var o,s;d.loginState="error",e.error?d.errorMessage=e.error:0<e.grace?(d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog.",e.grace)):0<e.expire?(s=86400<e.expire?(o=Math.round(e.expire/86400),l("days")):3600<e.expire?(o=Math.round(e.expire/3600),l("hours")):60<e.expire?(o=Math.round(e.expire/60),l("minutes")):(o=e.expire,l("seconds")),d.loginState="passwordwillexpire",d.cn=e.cn,d.url=e.url,d.errorMessage=l("Your password is going to expire in %{0} %{1}.",o,s)):e.passwordexpired&&(d.loginState="passwordchange",d.url=e.url)}),!1},this.restoreLogin=function(){d.showLogin=!1,"SecretQuestion"===d.passwordRecovery.passwordRecoveryMode?(t("loginContent"),d.passwordRecoveryInfo()):(delete d.creds.verificationCode,d.passwordRecoveryAbort())},this.continueLogin=function(){o.location.href===d.url?o.location.reload(!0):o.location.href=d.url},this.showAbout=function(e){function o(e){this.closeDialog=function(){e.hide()}}a.show({targetEvent:e,templateUrl:"aboutBox.html",controller:o,controllerAs:"about"}),o.$inject=["$mdDialog"]},this.changeLanguage=function(e){o.location.href=ApplicationBaseURL+"login?language="+this.creds.language},this.hello=function(e){return!1},this.canChangePassword=function(e){return this.passwords.newPasswordConfirmation&&this.passwords.newPasswordConfirmation.length&&this.passwords.newPassword!=this.passwords.newPasswordConfirmation?(e.newPasswordConfirmation.$setValidity("newPasswordMismatch",!1),!1):(e.newPasswordConfirmation.$setValidity("newPasswordMismatch",!0),!!(this.passwords.newPassword&&0<this.passwords.newPassword.length&&this.passwords.newPasswordConfirmation&&this.passwords.newPasswordConfirmation.length&&this.passwords.newPassword==this.passwords.newPasswordConfirmation&&(this.isInPasswordRecoveryMode()||!this.loginState&&this.passwords.oldPassword&&0<this.passwords.oldPassword.length||"passwordchange"==this.loginState&&this.passwords.oldPassword&&0<this.passwords.oldPassword.length)))},this.changePassword=function(){n.changePassword(this.creds.username,this.creds.domain,this.passwords.newPassword,this.passwords.oldPassword,this.passwordRecovery.passwordRecoveryToken).then(function(e){d.loginState="message",d.url=e.url,d.errorMessage=l("The password was changed successfully.")},function(e){d.loginState="error",d.errorMessage=e})},this.passwordRecoveryInfo=function(){d.loginState="passwordrecovery",d.passwordRecovery.showLoader=!0,n.passwordRecovery(this.creds.username,this.creds.domain).then(function(e){d.passwordRecovery.passwordRecoveryMode=e.mode,"SecretQuestion"===e.mode?(d.passwordRecovery.passwordRecoveryQuestion=e.secretQuestionLabel,d.passwordRecovery.passwordRecoveryQuestionKey=e.secretQuestion):"SecondaryEmail"===e.mode?d.passwordRecovery.passwordRecoverySecondaryEmailText=l("A link will be sent to %{0}",e.obfuscatedRecoveryEmail):"Disabled"===e.mode&&(d.loginState="error",d.errorMessage=l("No password recovery method has been defined for this user")),d.passwoLine truncated
//# sourceMappingURL=Main.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"Main.js","sources":["Main/Main.app.js"],"names":["angular","module","LoginController","$scope","$window","$timeout","Dialog","$mdDialog","Authentication","focus","rippleDo","vm","this","$onInit","creds","username","cookieUsername","password","domain","rememberLogin","isDefined","length","loginHint","test","location","search","language","loginState","verificationCodePattern","passwords","newPassword","newPasswordConfirmation","oldPassword","visible","passwordRecovery","passwordRecoveryEnabled","passwordRecoveryQuestionKey","passwordRecoveryQuestion","passwordRecoveryMode","passwordRecoveryQuestionAnswer","passwordRecoveryToken","passwordRecoveryLinkTimer","passwordRecoverySecondaryEmailText","passwordRecoveryMailDomain","showLoader","showLogin","queryString","window","let","token","URLSearchParams","get","pathname","indexOf","tokenArray","replace","split","info","JSON","parse","atob","retrievePasswordRecoveryEnabled","document","querySelectorAll","forEach","el","parentElement","classList","add","login","then","data","totpmissingkey","totpdisabled","cn","url","continueLogin","msg","value","string","error","errorMessage","grace","l","expire","Math","round","passwordexpired","loginName","restoreLogin","passwordRecoveryInfo","verificationCode","passwordRecoveryAbort","href","reload","showAbout","$event","AboutDialogController","closeDialog","hide","show","targetEvent","templateUrl","controller","controllerAs","$inject","changeLanguage","ApplicationBaseURL","hello","form","canChangePassword","$setValidity","isInPasswordRecoveryMode","changePassword","mode","secretQuestionLabel","secretQuestion","obfuscatedRecoveryEmail","passwordRecoveryEmail","passwordRecoveryCheck","usernameChanged","clearTimeout","setTimeout","mailDomain","changePasswordVisibility","field","getElementById","type","innerHTML"],"mappings":"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 truncated
{"version":3,"file":"Main.js","sources":["Main/Main.app.js"],"names":["angular","module","LoginController","$scope","$window","$timeout","Dialog","$mdDialog","Authentication","focus","rippleDo","vm","this","$onInit","creds","username","cookieUsername","password","domain","rememberLogin","isDefined","length","test","location","search","language","loginState","verificationCodePattern","passwords","newPassword","newPasswordConfirmation","oldPassword","visible","passwordRecovery","passwordRecoveryEnabled","passwordRecoveryQuestionKey","passwordRecoveryQuestion","passwordRecoveryMode","passwordRecoveryQuestionAnswer","passwordRecoveryToken","passwordRecoveryLinkTimer","passwordRecoverySecondaryEmailText","passwordRecoveryMailDomain","showLoader","showLogin","queryString","window","let","token","URLSearchParams","get","pathname","indexOf","tokenArray","replace","split","info","JSON","parse","atob","retrievePasswordRecoveryEnabled","document","querySelectorAll","forEach","el","parentElement","classList","add","login","then","data","totpmissingkey","totpdisabled","cn","url","continueLogin","msg","value","string","error","errorMessage","grace","l","expire","Math","round","passwordexpired","restoreLogin","passwordRecoveryInfo","verificationCode","passwordRecoveryAbort","href","reload","showAbout","$event","AboutDialogController","closeDialog","hide","show","targetEvent","templateUrl","controller","controllerAs","$inject","changeLanguage","ApplicationBaseURL","hello","form","canChangePassword","$setValidity","isInPasswordRecoveryMode","changePassword","mode","secretQuestionLabel","secretQuestion","obfuscatedRecoveryEmail","passwordRecoveryEmail","passwordRecoveryCheck","usernameChanged","clearTimeout","setTimeout","mailDomain","changePasswordVisibility","field","getElementById","type","innerHTML"],"mappings":"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 truncated
-60
View File
@@ -20,8 +20,6 @@
domain: null,
rememberLogin: angular.isDefined($window.cookieUsername) && $window.cookieUsername.length > 0
};
if($window.loginHint)
this.creds.username = $window.loginHint;
// Send selected language only if user has changed it
if (/\blanguage=/.test($window.location.search))
this.creds.language = $window.language;
@@ -159,64 +157,6 @@
return false;
};
this.loginName = function() {
vm.loginState = 'authenticating';
Authentication.loginName(vm.creds)
.then(function(data) {
vm.loginState = 'logged';
vm.cn = data.cn;
vm.url = data.url;
// Let the user see the succesfull message before reloading the page
$timeout(function() {
vm.continueLogin();
}, 1000);
}, function(msg) {
vm.loginState = 'error';
if (msg.error) {
vm.errorMessage = msg.error;
}
else if (msg.grace > 0) {
// Password is expired, grace logins limit is not yet reached
vm.loginState = 'passwordwillexpire';
vm.cn = msg.cn;
vm.url = msg.url;
vm.errorMessage = l('You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog.', msg.grace);
}
else if (msg.expire > 0) {
// Password will soon expire
var value, string;
if (msg.expire > 86400) {
value = Math.round(msg.expire/86400);
string = l("days");
}
else if (msg.expire > 3600) {
value = Math.round(msg.expire/3600);
string = l("hours");
}
else if (msg.expire > 60) {
value = Math.round(msg.expire/60);
string = l("minutes");
}
else {
value = msg.expire;
string = l("seconds");
}
vm.loginState = 'passwordwillexpire';
vm.cn = msg.cn;
vm.url = msg.url;
vm.errorMessage = l('Your password is going to expire in %{0} %{1}.', value, string);
}
else if (msg.passwordexpired) {
vm.loginState = 'passwordchange';
vm.url = msg.url;
}
});
return false;
};
this.restoreLogin = function() {
vm.showLogin = false;
if ('SecretQuestion' === vm.passwordRecovery.passwordRecoveryMode) {
+1 -1
View File
@@ -422,7 +422,7 @@ const punycode = {
* @memberOf punycode
* @type String
*/
'version': '2.1.0',
'version': '2.3.1',
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
@@ -50,13 +50,6 @@ $sg-login-width: grid-step(5);
margin-bottom: 8px;
}
.create-account-link {
color: rgb(255, 255, 255);
font-size: 1em;
text-decoration: none;
margin-bottom: 5px;
}
.password-lost-link {
color: rgb(255, 255, 255);
font-size: 0.9em;