rokwire / core-building-block

Building block which handles core functions for the Rokwire platform - users, accounts, profiles, organizations, authentication and authorization.
Apache License 2.0
3 stars 2 forks source link

[ID-680] Single identity within an organisation #684

Closed petyos closed 11 months ago

petyos commented 11 months ago

Description

Resolves #680

Here are the highlights of the changes:

type Account struct {
    ID string //this is ID for the account

    OrgID              string
    OrgAppsMemberships []OrgAppMembership

    /// Current App Org Membership // we keep this for easier migration to tenant accounts
    AppOrg                  ApplicationOrganization
    Permissions             []Permission
    Roles                   []AccountRole
    Groups                  []AccountGroup
    Preferences             map[string]interface{}
    MostRecentClientVersion *string
    /// End Current App Org Membership

    Scopes []string

    AuthTypes []AccountAuthType

    MFATypes []MFAType

    Username      string
    ExternalIDs   map[string]string
    SystemConfigs map[string]interface{}
    Profile       Profile //one account has one profile
    Privacy       Privacy

    Devices []Device

    Anonymous bool
    Verified  bool

    DateCreated time.Time
    DateUpdated *time.Time

    LastLoginDate       *time.Time
    LastAccessTokenDate *time.Time
}
type OrgAppMembership struct {
    ID     string
    AppOrg ApplicationOrganization

    Permissions []Permission
    Roles       []AccountRole
    Groups      []AccountGroup

    Preferences map[string]interface{}

    MostRecentClientVersion *string
}

In the account entity we have the organization and the apps which this account is attached within the organization. Also some of the old account properties are moved on OrgAppMembership level as permissions, roles, groups, preferences and most recent client version. One account has one profile.

We also keep this fields in the account:

    /// Current App Org Membership // we keep this for easier migration to tenant accounts
    AppOrg                  ApplicationOrganization
    Permissions             []Permission
    Roles                   []AccountRole
    Groups                  []AccountGroup
    Preferences             map[string]interface{}
    MostRecentClientVersion *string
    /// End Current App Org Membership

Actually this is the current app org membership but left them the way they are as they are used at many places. We can think of them as the current org app membership.

The old accounts collection is deprecated and we introduce a new collection called tenants_accounts. Here is the structure we keep in the collection:

type tenantAccount struct {
    ID string `bson:"_id"`

    OrgID              string             `bson:"org_id"`
    OrgAppsMemberships []orgAppMembership `bson:"org_apps_memberships"`

    Scopes []string `bson:"scopes,omitempty"`

    AuthTypes []accountAuthType `bson:"auth_types,omitempty"`

    MFATypes []mfaType `bson:"mfa_types,omitempty"`

    Username    string            `bson:"username"`
    ExternalIDs map[string]string `bson:"external_ids"`

    SystemConfigs map[string]interface{} `bson:"system_configs"`
    Profile       profile                `bson:"profile"`

    Devices []userDevice `bson:"devices,omitempty"`

    Anonymous bool          `bson:"anonymous"`
    Privacy   model.Privacy `bson:"privacy"`
    Verified  bool          `bson:"verified"`

    DateCreated time.Time  `bson:"date_created"`
    DateUpdated *time.Time `bson:"date_updated"`

    IsFollowing bool `bson:"is_following"`

    LastLoginDate       *time.Time `bson:"last_login_date"`
    LastAccessTokenDate *time.Time `bson:"last_access_token_date"`
}

type orgAppMembership struct {
    ID       string `bson:"id,omitempty"`
    AppOrgID string `bson:"app_org_id,omitempty"`

    Permissions []model.Permission `bson:"permissions,omitempty"`
    Roles       []accountRole      `bson:"roles,omitempty"`
    Groups      []accountGroup     `bson:"groups,omitempty"`

    Preferences map[string]interface{} `bson:"preferences"`

    MostRecentClientVersion *string `bson:"most_recent_client_version"`
}

In the storage we have a lot of code which actually moves the current records from the old accounts collection to the new tenants_accounts collection. All this happens on two phases. On first phase we care only the accounts which should be mixed. Once first phase is passed then we are sure that all accounts which left to be migrated should be moved into one to one. All this happens on the second phase. The second phase actually moves all the thousands record. We do this directly in the mongo server with one query at once interpolating the records in the new collection. This was tested with 93 000 records and it passed 70-80%. This is something which I will need to retest. All this code is in the database.go on startup.

The follwoing APIs were extended: Login, Get Account(and everywhere the account is given to the client) with a field called "apps" which says to which apps this account is attached. Delete Account API - the client can already says which apps the account wants to be removed from.

We also introduced a new field in the Application entity called "code" which is read only and not changable. The idea for this is the client to give comprehensive name for the user for example when asking him which apps to be removed instead of using the standard Application name field.

Currently we disable the code in storeSystemData which is not a critical functionality as of today, but at the same time, it relieves the workload on the tenant's account, which is of paramount importance. Over time, we will reintroduce it.

As general this refatoring affects many of the APIs in the Core BB and this is why we tested all fo them and they seem to work. Also, we will not need to support both types Services and Admin sections apis but this can happen piece by piece in the time. Currently the Services and Admin works with the refactoring changes.

Environemnt variables: export ROKWIRE_TAM_AUTH_TYPE_CODE_SOURCE=illinois_oidc

Add the field "code" manually for the applications collection. The values are: "client" - for the UIUC app "admin" - for the Admin app These fields were synchronized with the client team.

Thanks!