feat(acccount): Add read only account

This commit is contained in:
Hivert Quentin committed 2026-10-21 09:33:37 +02:00
1 parent 01f545b0b3
commit 370a4a433c
9 files changed
+120 -40

No files matched your search

@@ -2628,6 +2628,14 @@ from the SOGo Webmail interface.
Defaults to `NO` when unset.
|D |SOGoMailAuxiliaryUserAccountsReadOnly
|Only useful if `SOGoMailAuxiliaryUserAccountsEnabled = YES;`. Tell that auxiliiary
accounts are read-only and can only be set by admin with sogo-tool. User cannot
add external account nor modify them. Any previous external account not set by admin
will be removed.
Defaults to `NO` when unset.
|U |SOGoDefaultCalendar
|Parameter used to specify which calendar is used when creating an event
or a task. Possible values are:
+19 -1
View File
@@ -956,9 +956,27 @@ static NSString *inboxFolderName = @"INBOX";
}
else
{
password = [[self _mailAccount] objectForKey: @"password"];
if (!password)
password = @"";
{
SOGoDomainDefaults *dd;
dd = [[context activeUser] domainDefaults];
if([dd mailAuxiliaryUserAccountsReadOnly] && [[self _mailAccount] objectForKey: @"readOnly"])
{
//If we use aux account in read only, to not have a password means to use the current user one
imapURL = [self imap4URL];
password = [[self authenticatorInContext: context]
imapPasswordInContext: context
forURL: imapURL
forceRenew: renewed];
if (!password)
[self errorWithFormat: @"no IMAP4 password available"];
}
else
password = @"";
}
}
return password;
+1 -1
View File
@@ -37,7 +37,7 @@
- (BOOL) mailCustomFromEnabled;
- (BOOL) mailAuxiliaryUserAccountsEnabled;
- (BOOL) mailAuxiliaryUserAccountsReadOnly;
- (BOOL) mailDisableXForward;
- (NSString *) mailDomain;
- (NSString *) imapServer;
+5
View File
@@ -106,6 +106,11 @@
return [self boolForKey: @"SOGoMailAuxiliaryUserAccountsEnabled"];
}
- (BOOL) mailAuxiliaryUserAccountsReadOnly
{
return [self boolForKey: @"SOGoMailAuxiliaryUserAccountsReadOnly"];
}
- (BOOL) mailDisableXForward
{
return [self boolForKey: @"SOGoMailDisableXForward"];
+11
View File
@@ -276,6 +276,7 @@
NSURL * smtpUrl;
SOGoUser* user;
SOGoSystemDefaults *sd;
SOGoDomainDefaults *domainDefaults;
BOOL doSmtpAuth;
result = nil;
@@ -325,6 +326,16 @@
{
login = [currentAcount objectForKey: @"userName"];
password = [currentAcount objectForKey: @"password"];
domainDefaults = [[woContext activeUser] domainDefaults];
if(!password && [domainDefaults mailAuxiliaryUserAccountsReadOnly] && [currentAcount objectForKey: @"readOnly"])
{
//If aux account is read only with no password, user the current user one instead
protocol = @"imap";
if ([encryption isEqualToString: @"ssl"] || [encryption isEqualToString: @"tls"])
protocol = @"imaps";
server = [NSString stringWithFormat: @"%@://%@", protocol, [currentAcount objectForKey: @"serverName"]];
password = [authenticator smtpPasswordInContext: woContext forURL: server];
}
smtpAuthMethod = @"plain"; //Only support plain for auxiliary account
}
else
+4 -1
View File
@@ -1068,6 +1068,8 @@
[self _appendSystemMailAccountWithDelegatedIdentities: appendDeletegatedIdentities];
if ([[self domainDefaults] mailAuxiliaryUserAccountsEnabled])
{
//If we are in read-only, only add account with this param
auxAccounts = [[self userDefaults] auxiliaryMailAccounts];
if (auxAccounts)
{
@@ -1085,7 +1087,8 @@
account = [auxAccounts objectAtIndex: i];
if (![[account objectForKey: @"password"] isKindOfClass: [NSDictionary class]])
{
[self errorWithFormat:@"Can't decrypt the password for auxiliary account %@, is not a dictionnary",
if(![account objectForKey: @"readOnly"]) //Read only account can have no password
[self errorWithFormat:@"Can't decrypt the password for auxiliary account %@, is not a dictionnary",
[account objectForKey: @"name"]];
continue;
}
+39 -27
View File
@@ -506,31 +506,7 @@ static SoProduct *preferencesProduct = nil;
// Add timezone offset
[values setObject: [NSNumber numberWithInt: [[defaults timeZone] secondsFromGMT]] forKey: @"UserTimeZoneSecondsFromGMT"];
accounts = [NSMutableArray arrayWithArray: [values objectForKey: @"AuxiliaryMailAccounts"]];
if ([accounts count])
{
int i;
NSDictionary *security, *accountPassword;
NSMutableDictionary *auxAccount, *limitedSecurity;
NSString *password, *encryptedPassword, *sogoSecret, *iv, *tag;
NSException* exception = nil;
for (i = 0; i < [accounts count]; i++)
{
auxAccount = [accounts objectAtIndex: i];
security = [auxAccount objectForKey: @"security"];
if (security && [domainDefaults mailCertificateEnabled])
{
limitedSecurity = [NSMutableDictionary dictionaryWithDictionary: security];
if ([limitedSecurity objectForKey: @"certificate"])
{
[limitedSecurity setObject: [NSNumber numberWithBool: YES] forKey: @"hasCertificate"];
[limitedSecurity removeObjectForKey: @"certificate"];
}
[auxAccount setObject: limitedSecurity forKey: @"security"];
}
}
}
NSMutableArray *clean_accounts = [NSMutableArray array];
// We inject our default mail account
account = [[[context activeUser] mailAccountsNoRawHtmlSignature] objectAtIndex: 0];
if (![account objectForKey: @"receipts"])
@@ -542,8 +518,44 @@ static SoProduct *preferencesProduct = nil;
forKey: @"receipts"];
}
if (account)
[accounts insertObject: account atIndex: 0];
[values setObject: accounts forKey: @"AuxiliaryMailAccounts"];
[clean_accounts addObject: account];
//Now check external account
if (![domainDefaults mailAuxiliaryUserAccountsReadOnly] && [domainDefaults mailAuxiliaryUserAccountsEnabled])
{
accounts = [NSMutableArray arrayWithArray: [values objectForKey: @"AuxiliaryMailAccounts"]];
if ([accounts count])
{
int i;
NSDictionary *security, *accountPassword;
NSMutableDictionary *auxAccount, *limitedSecurity;
NSString *password, *encryptedPassword, *sogoSecret, *iv, *tag;
NSException* exception = nil;
BOOL isReadOnly = [domainDefaults mailAuxiliaryUserAccountsReadOnly];
for (i = 0; i < [accounts count]; i++)
{
auxAccount = [accounts objectAtIndex: i];
if(isReadOnly && [auxAccount objectForKey: @"readOnly"])
continue;
security = [auxAccount objectForKey: @"security"];
if (security && [domainDefaults mailCertificateEnabled])
{
limitedSecurity = [NSMutableDictionary dictionaryWithDictionary: security];
if ([limitedSecurity objectForKey: @"certificate"])
{
[limitedSecurity setObject: [NSNumber numberWithBool: YES] forKey: @"hasCertificate"];
[limitedSecurity removeObjectForKey: @"certificate"];
}
[auxAccount setObject: limitedSecurity forKey: @"security"];
}
[clean_accounts addObject: auxAccount];
}
}
}
[values setObject: clean_accounts forKey: @"AuxiliaryMailAccounts"];
// Ignore parameters as they are injected in the system mail account ([SOGoUser mailAccounts])
[values removeObjectForKey: @"SOGoMailIdentities"];
+26 -5
View File
@@ -1230,6 +1230,11 @@ static NSArray *reminderValues = nil;
return [[user domainDefaults] mailAuxiliaryUserAccountsEnabled];
}
- (BOOL) mailAuxiliaryUserAccountsReadOnly
{
return [[user domainDefaults] mailAuxiliaryUserAccountsReadOnly];
}
//
// Used internally
//
@@ -1534,15 +1539,30 @@ static NSArray *reminderValues = nil;
//
- (NSArray *) _extractAuxiliaryAccounts: (NSArray *) accounts
{
int count, max;
int count, i;
id isReadOnly;
NSMutableArray *auxAccounts;
NSMutableDictionary *account;
NSDictionary *currentAux, *auxAccount;
NSString *sogoSecret, *password;
max = [accounts count];
auxAccounts = [NSMutableArray arrayWithCapacity: max];
auxAccounts = [NSMutableArray array];
for (count = 1; count < max; count++)
if ([self mailAuxiliaryUserAccountsReadOnly]) {
//External account are read only. Meaning we don't accept any data from accounts
//Instead we fetch the current ones to not lost them
currentAux = [[[user userDefaults] source] objectForKey: @"AuxiliaryMailAccounts"];
for (i = 0; i < [currentAux count]; i++)
{
auxAccount = [currentAux objectAtIndex: i];
isReadOnly = [auxAccount objectForKey: @"readOnly"];
if(isReadOnly)
[auxAccounts addObject: auxAccount];
}
}
else
{
for (count = 1; count < [accounts count]; count++)
{
account = [accounts objectAtIndex: count];
if ([self _validateAccount: account])
@@ -1569,6 +1589,7 @@ static NSArray *reminderValues = nil;
[auxAccounts addObject: account];
}
}
}
return auxAccounts;
}
@@ -1863,7 +1884,7 @@ static NSArray *reminderValues = nil;
accounts = [v objectForKey: @"AuxiliaryMailAccounts"];
if (accounts && [accounts isKindOfClass: [NSArray class]])
{
if ([accounts count] > 0)
if ([accounts count] > 0 || [self mailAuxiliaryUserAccountsReadOnly]) //in the second case it's expected to have only the main account
{
// The first account is the main system account. The following mapping is required:
// - forceDefaultIdentity => SOGoMailForceDefaultIdentity
@@ -490,11 +490,13 @@
// Fetch draft initial data
return Account.$$resource.fetch(message.$absolutePath({asDraft: true}), 'edit').then(function(data) {
var accountDefaults = Account.$Preferences.defaults.AuxiliaryMailAccounts[_this.id];
if (accountDefaults.security) {
if (accountDefaults.security.alwaysSign)
data.sign = true;
if (accountDefaults.security.alwaysEncrypt)
data.encrypt = true;
if(accountDefaults) {
if (accountDefaults.security) {
if (accountDefaults.security.alwaysSign)
data.sign = true;
if (accountDefaults.security.alwaysEncrypt)
data.encrypt = true;
}
}
Account.$log.debug('New message (edit): ' + JSON.stringify(data, undefined, 2));
angular.extend(message.editable, data);