2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
// appUsers provides functions to sign Seekia users in and out, and to manage Seekia users
|
|
|
|
// These are the users that are displayed in the gui upon starting Seekia
|
|
|
|
// Each user has its own data folder, allowing each user to operate different identities.
|
|
|
|
|
|
|
|
package appUsers
|
|
|
|
|
|
|
|
// The functions in this package are not safe for concurrency
|
|
|
|
// The GUI should prevent any concurrent use of these functions
|
|
|
|
|
|
|
|
import "seekia/resources/geneticReferences/locusMetadata"
|
|
|
|
import "seekia/resources/geneticReferences/monogenicDiseases"
|
|
|
|
import "seekia/resources/geneticReferences/polygenicDiseases"
|
|
|
|
import "seekia/resources/geneticReferences/traits"
|
|
|
|
import "seekia/resources/worldLanguages"
|
|
|
|
import "seekia/resources/worldLocations"
|
|
|
|
|
|
|
|
import "seekia/internal/appMemory"
|
|
|
|
import "seekia/internal/backgroundJobs"
|
|
|
|
import "seekia/internal/desires/myLocalDesires"
|
|
|
|
import "seekia/internal/encoding"
|
|
|
|
import "seekia/internal/genetics/myAnalyses"
|
|
|
|
import "seekia/internal/genetics/myCouples"
|
|
|
|
import "seekia/internal/genetics/myGenomes"
|
|
|
|
import "seekia/internal/genetics/myPeople"
|
|
|
|
import "seekia/internal/localFilesystem"
|
|
|
|
import "seekia/internal/logger"
|
|
|
|
import "seekia/internal/messaging/myChatConversations"
|
|
|
|
import "seekia/internal/messaging/myChatFilters"
|
|
|
|
import "seekia/internal/messaging/myChatKeys"
|
|
|
|
import "seekia/internal/messaging/myChatMessages"
|
|
|
|
import "seekia/internal/messaging/myCipherKeys"
|
|
|
|
import "seekia/internal/messaging/myConversationIndexes"
|
|
|
|
import "seekia/internal/messaging/myMessageQueue"
|
|
|
|
import "seekia/internal/messaging/myReadStatus"
|
|
|
|
import "seekia/internal/messaging/mySecretInboxes"
|
|
|
|
import "seekia/internal/messaging/peerChatKeys"
|
|
|
|
import "seekia/internal/messaging/peerDevices"
|
|
|
|
import "seekia/internal/messaging/peerSecretInboxes"
|
|
|
|
import "seekia/internal/messaging/sendMessages"
|
|
|
|
import "seekia/internal/moderation/myHiddenContent"
|
|
|
|
import "seekia/internal/moderation/mySkippedContent"
|
|
|
|
import "seekia/internal/moderation/viewedContent"
|
|
|
|
import "seekia/internal/moderation/viewedModerators"
|
|
|
|
import "seekia/internal/myBlockedUsers"
|
|
|
|
import "seekia/internal/myContacts"
|
|
|
|
import "seekia/internal/myDatastores/myList"
|
|
|
|
import "seekia/internal/myDatastores/myMap"
|
|
|
|
import "seekia/internal/myDatastores/myMapList"
|
|
|
|
import "seekia/internal/myIgnoredUsers"
|
|
|
|
import "seekia/internal/myLikedUsers"
|
|
|
|
import "seekia/internal/myMatches"
|
|
|
|
import "seekia/internal/myMatchScore"
|
|
|
|
import "seekia/internal/mySeedPhrases"
|
|
|
|
import "seekia/internal/mySettings"
|
|
|
|
import "seekia/internal/network/myBroadcasts"
|
|
|
|
import "seekia/internal/network/myMateCriteria"
|
|
|
|
import "seekia/internal/network/peerServer"
|
|
|
|
import "seekia/internal/network/viewedHosts"
|
|
|
|
import "seekia/internal/profiles/myLocalProfiles"
|
|
|
|
import "seekia/internal/profiles/profileFormat"
|
|
|
|
|
|
|
|
import "errors"
|
|
|
|
import "os"
|
|
|
|
import "strings"
|
|
|
|
import "sync"
|
|
|
|
import "time"
|
|
|
|
import "unicode"
|
|
|
|
|
|
|
|
import goFilepath "path/filepath"
|
|
|
|
|
|
|
|
// This bool is set to true if we have initialized application variables
|
|
|
|
// These only need to be initialized once for all users each time the application is started
|
|
|
|
var applicationVariablesInitialized bool = false
|
|
|
|
|
|
|
|
func SignInToAppUser(userName string, startBackgroundJobs bool)error{
|
|
|
|
|
|
|
|
appMemory.SetMemoryEntry("AppUser", userName)
|
|
|
|
|
2024-06-07 03:33:10 +02:00
|
|
|
err := createAppUserDataFolders()
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
2024-06-07 03:33:10 +02:00
|
|
|
err = initializeAppUserDatastores()
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myAnalyses.PruneOldAnalyses()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
if (applicationVariablesInitialized == false){
|
|
|
|
|
|
|
|
// This only needs to be done once per application startup
|
|
|
|
|
2024-06-07 03:33:10 +02:00
|
|
|
err := initializeApplicationVariables()
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
applicationVariablesInitialized = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if (startBackgroundJobs == true){
|
|
|
|
|
|
|
|
err = backgroundJobs.StartBackgroundJobs()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func SignOutOfAppUser()error{
|
|
|
|
|
|
|
|
var signOutWaitgroup sync.WaitGroup
|
|
|
|
|
|
|
|
stopBackgroundJobs := func(){
|
|
|
|
|
|
|
|
err := backgroundJobs.StopBackgroundJobs()
|
|
|
|
if (err != nil) {
|
|
|
|
//TODO: Log and show to user
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
signOutWaitgroup.Done()
|
|
|
|
}
|
|
|
|
|
|
|
|
waitForSendsToComplete := func(){
|
|
|
|
|
|
|
|
sendMessages.WaitForPendingSendsToComplete()
|
|
|
|
|
|
|
|
signOutWaitgroup.Done()
|
|
|
|
}
|
|
|
|
|
|
|
|
stopPeerServer := func(){
|
|
|
|
|
|
|
|
err := peerServer.StopPeerServer()
|
|
|
|
if (err != nil){
|
|
|
|
//TODO: Log and show to user
|
|
|
|
}
|
|
|
|
|
|
|
|
signOutWaitgroup.Done()
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: Wait for manual downloads and manual broadcasts to finish
|
|
|
|
|
|
|
|
signOutWaitgroup.Add(3)
|
|
|
|
|
|
|
|
go stopBackgroundJobs()
|
|
|
|
go waitForSendsToComplete()
|
|
|
|
go stopPeerServer()
|
|
|
|
|
|
|
|
//TODO: Wait for other tasks that use userData folders
|
|
|
|
|
|
|
|
signOutWaitgroup.Wait()
|
|
|
|
|
|
|
|
// We simulate some time. This will be removed once the above functions are implemented
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
|
|
|
appMemory.ClearAppMemory()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func VerifyAppUserNameCharactersAreAllowed(userName string)bool{
|
|
|
|
|
|
|
|
// The user name becomes the name of a folder on the filesystem
|
|
|
|
// Thus, we only allow letters and numbers
|
|
|
|
|
|
|
|
const digitsList = "0123456789"
|
|
|
|
|
|
|
|
for _, character := range userName {
|
|
|
|
|
|
|
|
isLetter := unicode.IsLetter(character)
|
|
|
|
if (isLetter == true){
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
isDigit := strings.Contains(digitsList, string(character))
|
|
|
|
if (isDigit == true){
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func GetAppUsersList()([]string, error){
|
|
|
|
|
|
|
|
appUsersDirectory, err := localFilesystem.GetAppUsersDataFolderPath()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
filesystemList, err := os.ReadDir(appUsersDirectory)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
allUsersList := make([]string, 0, len(filesystemList))
|
|
|
|
|
|
|
|
for _, filesystemObject := range filesystemList{
|
|
|
|
|
|
|
|
filepathIsDirectory := filesystemObject.IsDir()
|
|
|
|
if (filepathIsDirectory == false){
|
|
|
|
return nil, errors.New("UserData folder is corrupt: Contains non-folder: " + filesystemObject.Name())
|
|
|
|
}
|
|
|
|
|
|
|
|
folderName := filesystemObject.Name()
|
|
|
|
|
|
|
|
isValid := VerifyAppUserNameCharactersAreAllowed(folderName)
|
|
|
|
if (isValid == false){
|
|
|
|
return nil, errors.New("UserData folder is corrupt: Contains invalid folder name: " + folderName)
|
|
|
|
}
|
|
|
|
|
|
|
|
allUsersList = append(allUsersList, folderName)
|
|
|
|
}
|
|
|
|
|
|
|
|
return allUsersList, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Outputs:
|
|
|
|
// -bool: App user exists
|
|
|
|
// -string: User name
|
|
|
|
func GetCurrentAppUserName()(bool, string){
|
|
|
|
|
|
|
|
exists, appUserName := appMemory.GetMemoryEntry("AppUser")
|
|
|
|
if (exists == false){
|
|
|
|
return false, ""
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, appUserName
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Outputs:
|
|
|
|
// -bool: Name is a duplicate
|
|
|
|
// -error
|
|
|
|
func CreateAppUser(newUserName string)(bool, error){
|
|
|
|
|
|
|
|
if (newUserName == ""){
|
|
|
|
return false, errors.New("CreateAppUser called with empty user name.")
|
|
|
|
}
|
|
|
|
if (len(newUserName) > 30){
|
|
|
|
return false, errors.New("CreateAppUser called with user name that is too long: " + newUserName)
|
|
|
|
}
|
|
|
|
|
|
|
|
isAllowed := VerifyAppUserNameCharactersAreAllowed(newUserName)
|
|
|
|
if (isAllowed == false){
|
|
|
|
return false, errors.New("CreateAppUser called with user name contains unallowed characters: " + newUserName)
|
|
|
|
}
|
|
|
|
|
|
|
|
appUsersList, err := GetAppUsersList()
|
|
|
|
if (err != nil){ return false, err }
|
|
|
|
|
|
|
|
for _, existingUser := range appUsersList{
|
|
|
|
if (existingUser == newUserName){
|
|
|
|
// User name already exists
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
appUsersDirectory, err := localFilesystem.GetAppUsersDataFolderPath()
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
userFolderpath := goFilepath.Join(appUsersDirectory, newUserName)
|
|
|
|
|
|
|
|
_, err = localFilesystem.CreateFolder(userFolderpath)
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
|
|
|
|
// We set the IsIgnored desire
|
|
|
|
// This desire is initialized upon user creation, so ignored users will be hidden
|
|
|
|
// The user can disable this desire
|
|
|
|
// We have to sign in to do this
|
|
|
|
|
|
|
|
err = SignInToAppUser(newUserName, false)
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
err = myLocalDesires.SetDesire("IsIgnored_FilterAll", "Yes")
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
// Desire value is a "+" delimited list of base64 choices which we desire
|
|
|
|
// "No" == We desire users who are not ignored
|
|
|
|
noBase64 := encoding.EncodeBytesToBase64String([]byte("No"))
|
|
|
|
|
|
|
|
err = myLocalDesires.SetDesire("IsIgnored", noBase64)
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
// We clear app memory to "sign out" of app user
|
|
|
|
appMemory.ClearAppMemory()
|
|
|
|
|
|
|
|
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
//Outputs:
|
|
|
|
// -bool: User is found
|
|
|
|
// -error
|
|
|
|
func RenameAppUser(userName string, newUserName string)(bool, error){
|
|
|
|
|
|
|
|
err := SignOutOfAppUser()
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
appUsersDirectory, err := localFilesystem.GetAppUsersDataFolderPath()
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
currentUserFolderpath := goFilepath.Join(appUsersDirectory, userName)
|
|
|
|
newUserFolderpath := goFilepath.Join(appUsersDirectory, newUserName)
|
|
|
|
|
|
|
|
err = os.Rename(currentUserFolderpath, newUserFolderpath)
|
|
|
|
if (err != nil){
|
|
|
|
folderDoesNotExist := os.IsNotExist(err)
|
|
|
|
if (folderDoesNotExist == true){
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Outputs:
|
|
|
|
// -bool: User found
|
|
|
|
// -error
|
|
|
|
func DeleteAppUser(userName string)(bool, error){
|
|
|
|
|
|
|
|
err := SignOutOfAppUser()
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
appUsersDirectory, err := localFilesystem.GetAppUsersDataFolderPath()
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
|
|
|
|
userFolderPath := goFilepath.Join(appUsersDirectory, userName)
|
|
|
|
|
|
|
|
folderExists, err := localFilesystem.DeleteAllFolderContents(userFolderPath)
|
|
|
|
if (err != nil){ return false, err }
|
|
|
|
if (folderExists == false){
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
folderExists, err = localFilesystem.DeleteFileOrFolder(userFolderPath)
|
|
|
|
if (err != nil) { return false, err }
|
|
|
|
if (folderExists == false){
|
|
|
|
return false, errors.New("User data folder not found after call to DeleteAllFolderContents")
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// We use this to partially sign in to the first app user when testing packages that need it
|
|
|
|
// An example is myMap, which requires an app user to be signed in to use it
|
|
|
|
// We don't need to sign the user out after calling this function, because we only use this for testing
|
2024-06-07 03:33:10 +02:00
|
|
|
func InitializeAppUserForTests(initializeAppDatastores bool, initializeAppVariables bool)error{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
appUsersList, err := GetAppUsersList()
|
|
|
|
if (err != nil){ return err }
|
|
|
|
|
|
|
|
if (len(appUsersList) == 0){
|
|
|
|
return errors.New("SignInToAppUserForTests called when no app users exist.")
|
|
|
|
}
|
|
|
|
|
|
|
|
userName := appUsersList[0]
|
|
|
|
|
|
|
|
appMemory.SetMemoryEntry("AppUser", userName)
|
|
|
|
|
2024-06-07 03:33:10 +02:00
|
|
|
err = createAppUserDataFolders()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
if (initializeAppDatastores == true){
|
|
|
|
|
|
|
|
err := initializeAppUserDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
}
|
|
|
|
|
|
|
|
if (initializeAppVariables == true){
|
|
|
|
|
|
|
|
err := initializeApplicationVariables()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func initializeApplicationVariables()error{
|
|
|
|
|
|
|
|
// This only needs to be done once per application startup
|
|
|
|
|
|
|
|
err := worldLocations.InitializeWorldLocationsVariables()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = worldLanguages.InitializeWorldLanguageVariables()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = locusMetadata.InitializeLocusMetadataVariables()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
monogenicDiseases.InitializeMonogenicDiseaseVariables()
|
|
|
|
|
|
|
|
polygenicDiseases.InitializePolygenicDiseaseVariables()
|
|
|
|
|
2024-08-05 09:11:10 +02:00
|
|
|
err = traits.InitializeTraitVariables()
|
|
|
|
if (err != nil) { return err }
|
2024-06-07 03:33:10 +02:00
|
|
|
|
|
|
|
err = profileFormat.InitializeProfileFormatVariables()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func createAppUserDataFolders()error{
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
userDirectoryPath, err := localFilesystem.GetAppUserFolderPath()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
_, err = localFilesystem.CreateFolder(userDirectoryPath)
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myMap.InitializeMyMapsFolder()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myList.InitializeMyListsFolder()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myMapList.InitializeMyMapListsFolder()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
2024-06-07 03:33:10 +02:00
|
|
|
err = myBroadcasts.InitializeMyBroadcastsFolders()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myGenomes.CreateUserGenomesFolder()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myAnalyses.CreateMyAnalysesFolder()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-06-07 03:33:10 +02:00
|
|
|
func initializeAppUserDatastores()error{
|
|
|
|
|
|
|
|
err := mySeedPhrases.InitializeMySeedPhrasesDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myLocalDesires.InitializeMyDesiresDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myMateCriteria.InitializeMyCriteriaDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myMatchScore.InitializeMyMatchScorePointsDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = mySettings.InitializeMySettingsDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myLocalProfiles.InitializeMyLocalProfileDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myMatches.InitializeMyMatchesDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myContacts.InitializeMyContactDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myIgnoredUsers.InitializeMyIgnoredUsersDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myBlockedUsers.InitializeMyBlockedUsersDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = mySecretInboxes.InitializeMySecretInboxesDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myChatKeys.InitializeMyChatKeysDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myCipherKeys.InitializeMyMessageCipherKeysDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myReadStatus.InitializeMyReadStatusDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myConversationIndexes.InitializeMyConversationIndexesDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myChatFilters.InitializeMyChatFiltersDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myLikedUsers.InitializeMyLikedUsersDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myChatConversations.InitializeMyChatConversationsDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myChatMessages.InitializeMyChatMessageDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myMessageQueue.InitializeMyMessageQueueDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = peerChatKeys.InitializePeerChatKeysDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = peerSecretInboxes.InitializePeerSecretInboxesDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = peerDevices.InitializePeerDevicesDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = sendMessages.InitializeSentMessagesDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myGenomes.InitializeMyGenomeDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myPeople.InitializeMyGenomePeopleDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myCouples.InitializeMyGenomeCouplesDatastore()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myAnalyses.InitializeMyAnalysesDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = viewedContent.InitializeViewedContentDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = logger.InitializeMyLogDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = viewedModerators.InitializeViewedModeratorsDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = viewedHosts.InitializeViewedHostsDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = mySkippedContent.InitializeMySkippedContentDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
err = myHiddenContent.InitializeMyHiddenContentDatastores()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
|