Best practices to store user information/settings in Caché
I'm interested in different approaches on how to store user data in Caché. I'm assuming that application uses Caché security/Caché users and not a self-made authentication system.
Several approaches, I'm familiar with:
1. Store data in Security.Users:Attributes property. Sample methods:
/// Set settings for User equal to Settings
ClassMethod SetSettings(Settings As %String = "", User As %String = {$Username}) As %Status
{
New $Namespace
Set $Namespace = "%SYS"
Set Properties("Attributes", "Settings") = $LB(Config)
Set st = ##class(Security.Users).Modify(User, .Properties)
Return st
}
/// Get settings for User
ClassMethod GetSettings(User As %String = {$Username}) As %String
{
New $Namespace
Set $Namespace = "%SYS"
Set st = ##class(Security.Users).Get(User, .Properties)
Return $ListGet($Get(Properties("Attributes", "Settings")))
}
Advantages:
- Easy to implement
- Easy to retrieve some system information about user
Disadvantages:
- Requires resources
%DB_CACHESYS:RW, %Admin_Secure:U
2. Reference Security.Users as a property from your own class. Sample class:
Class Utils.UserInfo Extends %Persistent
{
Property User As Security.Users;
Property Settings As %String;
Index UserIndex On User [ IdKey, PrimaryKey, Unique ];
/// Set settings for User equal to Settings
ClassMethod SetSettings(Settings As %String = "", User As %String = {$Username}) As %Status
{
If ..%ExistsId(User) {
Set settingsObj = ..%OpenId(User)
} Else {
Set settingsObj = ..%New()
Set userObj = ##class(Security.Users).%OpenId(User)
Set settingsObj.User = userObj
}
Set settingsObj.Settings = Settings
Return settingsObj.%Save()
}
/// Get settings for User
ClassMethod GetSettings(User As %String = {$Username}) As %String
{
Return ..SettingsGetStored(User)
}
}
Advantages:
- Does not need to open an object to retrieve settings
Disadvantages:
- Requires mapping of Security.Users class to an application namespace
3. Reference User as a string property. About the same as the previous option. Sample class:
Class Utils.UserInfo Extends %Persistent
{
Property User As %String;
Property Settings As %String;
Index UserIndex On User [ IdKey, PrimaryKey, Unique ];
/// Set settings for User equal to Settings
ClassMethod SetSettings(Settings As %String = "", User As %String = {$Username}) As %Status
{
If ..%ExistsId(User) {
Set settingsObj = ..%OpenId(User)
} Else {
Set settingsObj = ..%New()
Set settingsObj.User = User
}
Set settingsObj.Settings = Settings
Return settingsObj.%Save()
}
/// Get settings for User
ClassMethod GetSettings(User As %String = {$Username}) As %String
{
Return ..SettingsGetStored(User)
}
}
Advantages:
- Does not need to open an object to retrieve settings
Disadvantages:
- Invalid data may be entered, the check that username is correct would again require some form of access to Security.Users
4. Store settings in global. Sample methods:
/// Set settings for User equal to Settings
ClassMethod SetConfig(Config As %String = "", User As %String = {$Username}) As %Status
{
Set ^SettingsGlobal(User) = Config
Return $$$OK
}
/// Get settings for User
ClassMethod GetConfig(App As %String, User As %String = {$Username}) As %String
{
Return $Get(^SettingsGlobal(User))
}
Advantages:
- Easy to set up
- Does not need to open an object to set or retrieve settings
Disadvantages:
- Invalid data may be entered, the check that username is correct would again require some form of access to Security.Users
- No object or SQL access
So, are there any other solutions? Moreover, what is the best approach?