// Use it to import from resource - look at ImportDefaultSecretQuestions
        public static int ImportSecretQuestions(IEntitySession session, Stream stream)
        {
            var reader = new StreamReader(stream);
            var text   = reader.ReadToEnd(); // File.ReadAllLines(filePath);
            var lines  = text.Split(new [] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            // Postgres blows up here, trying with LINQ
            //var oldList = session.GetEntities<ISecretQuestion>();
            var oldList = session.EntitySet <ISecretQuestion>().ToList();
            var count   = 0;

            foreach (var line in lines)
            {
                if (string.IsNullOrWhiteSpace(line) || line.StartsWith("//"))
                {
                    continue;
                }
                //check if there's existing
                var trimLine = line.Trim();
                var oldLine  = oldList.FirstOrDefault(l => l.Question == trimLine);
                if (oldLine != null)
                {
                    continue;
                }
                var q = session.NewEntity <ISecretQuestion>();
                q.Question = trimLine;
                q.Number   = count++;
                q.Flags    = SecretQuestionFlags.None;
            }
            return(count);
        }
        }     // method

        private void CreateNextRunsForScheduledRuns(IEntitySession session, IList <IJobRun> jobRuns, DateTime utcNow)
        {
            //Find all schedules involed with these jobs/runs
            var jobIds = jobRuns.Select(j => j.Job.Id).ToList();
            var scheds = session.EntitySet <IJobSchedule>().Where(js => jobIds.Contains(js.Job.Id)).ToList();

            if (scheds.Count == 0)
            {
                return;
            }
            foreach (var sched in scheds)
            {
                var nextStartOn = sched.GetNextStartAfter(utcNow);
                if (nextStartOn != null)
                {
                    var nextRun = NewJobRun(sched.Job, JobRunType.Schedule, nextStartOn);
                    sched.NextRunId = nextRun.Id;
                }
                else
                {
                    sched.NextRunId = null;
                    sched.Status    = JobScheduleStatus.Stopped;
                }
            } //foreach
        }     //method
        public IOAuthClientFlow GetOAuthFlow(IEntitySession session, Guid flowId)
        {
            // Limit to logged in user, to avoid authorizatio exception
            var query = session.EntitySet <IOAuthClientFlow>().Where(f => f.Id == flowId);
            var user  = session.Context.User;

            if (user.Kind == UserKind.AuthenticatedUser)
            {
                query = query.Where(f => f.UserId == user.UserId);
            }
            var flow = query.FirstOrDefault();

            if (flow == null)
            {
                return(null);
            }
            if (flow.UserId != null)
            {
                var currUserId = session.Context.User.UserId;
                if (currUserId != flow.UserId.Value)
                {
                    return(null);
                }
            }
            CheckExpired(flow);
            return(flow);
        }
        //Low-level methods
        public ILogin FindLogin(IEntitySession session, string userName, string password, Guid?tenantId)
        {
            var context = session.Context;

            context.ValidateNotEmpty(userName, ClientFaultCodes.ValueMissing, "UserName", null, "UserName may not be empty");
            context.ValidateNotEmpty(password, ClientFaultCodes.ValueMissing, "Password", null, "Password may not be empty");
            context.ThrowValidation();
            userName = CheckUserName(context, userName);
            var userNameHash  = Util.StableHash(userName);
            var weakPwdHash   = GetWeakPasswordHash(password);
            var tenantIdValue = tenantId == null ? Guid.Empty : tenantId.Value;
            // Note: we do not compare usernames, only UserNameHash values; UserName might be null if we don't save them
            var qryLogins = from lg in session.EntitySet <ILogin>()
                            where lg.UserNameHash == userNameHash && lg.WeakPasswordHash == weakPwdHash &&
                            lg.TenantId == tenantIdValue
                            select lg;

            //Query logins table
            using (session.WithElevateRead()) {
                var logins = qryLogins.ToList(); //these are candidates, but most often will be just one
                var login  = logins.FirstOrDefault(lg => VerifyPassword(lg, password));
                if (login != null)
                {
                    VerifyExpirationSuspensionDates(login);
                }
                return(login);
            }
        }
示例#5
0
        public IList <DataHistoryEntry> GetEntityHistory(IEntitySession session, Type entityType, object primaryKey,
                                                         DateTime?fromDate = null, DateTime?tillDate = null, int skip = 0, int take = 100, Guid?userId = null)
        {
            var entInfo = session.Context.App.Model.GetEntityInfo(entityType);

            Util.Check(entInfo != null, "Type {0} is not registered as an entity.", entityType);
            var entName     = entInfo.FullName;
            var entNameHash = Util.StableHash(entName);

            var where = session.NewPredicate <IDataHistory>()
                        .And(h => h.EntityNameHash == entNameHash && h.EntityName == entName)
                        .AndIfNotEmpty(fromDate, h => h.CreatedOn > fromDate.Value)
                        .AndIfNotEmpty(tillDate, h => h.CreatedOn < tillDate.Value);
            if (primaryKey != null)
            {
                var pkStr  = PrimaryKeyAsString(primaryKey);
                var pkHash = Util.StableHash(pkStr);
                where = where.And(h => h.EntityPrimaryKeyHash == pkHash && h.EntityPrimaryKey == pkStr);
            }
            var query       = session.EntitySet <IDataHistory>().Where(where).OrderByDescending(h => h.CreatedOn).Skip(skip).Take(take);
            var histEntList = query.ToList();
            var result      = histEntList.Select(h => h.ToHistoryEntry(entInfo)).ToList();

            return(result);
        }
示例#6
0
        public ILoginProcess GetActiveProcess(IEntitySession session, LoginProcessType processType, string token)
        {
            Util.Check(!string.IsNullOrWhiteSpace(token), "Process token may not be null");
            var context = session.Context;
            //get process without expiration checking, we check it later
            var query = from p in session.EntitySet <ILoginProcess>()
                        where p.ProcessType == processType && p.Token == token
                        select p;
            var process = query.FirstOrDefault();

            context.ThrowIfNull(process, ClientFaultCodes.ObjectNotFound, "Process", "Login process not found.");
            if (process.Status != LoginProcessStatus.Active)
            {
                return(null);
            }
            if (process.FailCount >= _settings.MaxFailCount)
            {
                process.Status = LoginProcessStatus.AbortedAsFraud;
                OnLoginEvent(context, LoginEventType.ProcessAborted, process.Login, "Aborted - too many failures.");
                session.SaveChanges();
                return(null);
            }
            var userName = process.Login.UserName;

            if (process.ExpiresOn < App.TimeService.UtcNow)
            {
                process.Status = LoginProcessStatus.Expired;
                OnLoginEvent(context, LoginEventType.ProcessAborted, process.Login, "Expired.");
                session.SaveChanges();
                return(null);
            }
            return(process);
        }
示例#7
0
 internal static void UpdateStatus(this IEntitySession session, Guid tokenId, OAuthTokenStatus status)
 {
     var updQuery = from t in session.EntitySet <IOAuthAccessToken>()
                    where t.Id == tokenId
                    select new { Id = t.Id, Status = status };
     var cnt = updQuery.ExecuteUpdate <IOAuthAccessToken>();
 }
示例#8
0
        /// <summary>Returns the last finished (non-Pending) job run for a given job.</summary>
        /// <param name="session">Entity session.</param>
        /// <param name="jobId">Job ID.</param>
        /// <returns>Job run entity if found, null otherwise.</returns>
        public static IJobRun GetLastFinishedJobRun(this IEntitySession session, Guid jobId)
        {
            var jobRun = session.EntitySet <IJobRun>().Where(jr => jr.Job.Id == jobId)
                         .Where(jr => jr.Status != JobRunStatus.Pending)
                         .OrderByDescending(jr => jr.AttemptNumber).FirstOrDefault();

            return(jobRun);
        }
示例#9
0
        public ILoginExtraFactor FindLoginExtraFactor(IEntitySession session, ExtraFactorTypes factorType, string factor)
        {
            var entFactor = session.EntitySet <ILoginExtraFactor>()
                            .FirstOrDefault(ef => ef.FactorType == factorType && ef.FactorValue == factor);

            VerifyExpirationSuspensionDates(entFactor.Login);
            return(entFactor);
        }
示例#10
0
        // Can be called explicitly outside of migrations to unencrypt existing values
        public static void UnencryptFactorValues(IEntitySession session)
        {
            var loginConfig = session.Context.App.GetConfig <LoginModuleSettings>();
            var errLog      = session.Context.App.ErrorLog;
            int batchSize   = 200;
            int skip        = 0;

            try {
                var factors = session.EntitySet <ILoginExtraFactor>()
                              .Where(f => f.FactorValue == null).OrderBy(f => f.CreatedOn)
                              .Skip(skip).Take(batchSize).ToList();
                skip += batchSize;
                if (factors.Count == 0)
                {
                    return;
                }
                //preload all EncryptedValue records
                var encrIds  = factors.Select(f => f.Info_Id).ToList();
                var encrRecs = session.EntitySet <IEncryptedData>().Where(ed => encrIds.Contains(ed.Id));
                foreach (var f in factors)
                {
                    if (f.Info_Id == null || f.Info_Id.Value == Guid.Empty)
                    {
                        continue;
                    }
                    var ed = session.GetEntity <IEncryptedData>(f.Info_Id); //should be preloaded
                    if (ed == null)
                    {
                        continue;
                    }
                    f.FactorValue = ed.DecryptString(loginConfig.EncryptionChannelName);
                    f.Info_Id     = null;
                }
                session.SaveChanges();
            } catch (Exception ex) {
                if (errLog != null)
                {
                    errLog.LogError(ex, session.Context);
                }
                if (!SuppressMigrationErrors)
                {
                    throw;
                }
            }
        }
示例#11
0
        public static ICoupon LookupCoupon(this IEntitySession session, string code)
        {
            var query = from c in session.EntitySet <ICoupon>()
                        where c.PromoCode == code
                        select c;
            var coupon = query.FirstOrDefault();

            return(coupon);
        }
示例#12
0
 public ITextTemplate GetTemplate(IEntitySession session, string templateName, string culture = "EN-US", Guid? ownerId = null)
 {
     var where = session.NewPredicate<ITextTemplate>()
     .And(t => t.Name == templateName)
     .AndIfNotEmpty(culture, t => t.Culture == culture)
     .AndIfNotEmpty(ownerId, t => t.OwnerId == ownerId.Value);
       var template = session.EntitySet<ITextTemplate>().Where(where).FirstOrDefault();
       return template;
 }
示例#13
0
        public static IQueryable <TEntity> EntitySet <TEntity>(this IEntitySession session, LockType lockType) where TEntity : class
        {
            if (lockType == LockType.None)
            {
                return(session.EntitySet <TEntity>());
            }
            var entSession = (EntitySession)session;

            return(entSession.CreateEntitySet <TEntity>(lockType));
        }
示例#14
0
        public static IQueryable <TEntity> EntitySet <TEntity>(this IEntitySession session, LockOptions options) where TEntity : class
        {
            if (options == LockOptions.None)
            {
                return(session.EntitySet <TEntity>());
            }
            var entSession = (EntitySession)session;

            return(entSession.CreateEntitySet <TEntity>(options));
        }
示例#15
0
        public ITextTemplate GetTemplate(IEntitySession session, string templateName, string culture = "EN-US", Guid?ownerId = null)
        {
            var where = session.NewPredicate <ITextTemplate>()
                        .And(t => t.Name == templateName)
                        .AndIfNotEmpty(culture, t => t.Culture == culture)
                        .AndIfNotEmpty(ownerId, t => t.OwnerId == ownerId.Value);
            var template = session.EntitySet <ITextTemplate>().Where(where).FirstOrDefault();

            return(template);
        }
示例#16
0
        public IList <ISecretQuestion> GetAllSecretQuestions(IEntitySession session)
        {
            var mask  = SecretQuestionFlags.Disabled | SecretQuestionFlags.Private;
            var query = from q in session.EntitySet <ISecretQuestion>()
                        where (q.Flags & mask) == 0 //we look for public and enabled
                        orderby q.Number
                        select q;
            var questions = query.ToList();

            return(questions);
        }
示例#17
0
 //Alice defines a utility method to login users.
 public static ILogin Login(IEntitySession session, string userName, 
     int passwordHash)
 {
     // For simplicity, we use direct LINQ
     var query = from login in session.EntitySet<ILogin>()
         where login.UserName == userName &&
               login.PasswordHash == passwordHash
         select login;
     var logins = query.ToList();
     return logins.Count == 0 ? null : logins[0];
 }
示例#18
0
            public void SaveObjects(IEntitySession session, IList <object> items)
            {
                //Schedule update query that will update all LastActiveOn columns for all sessions with ID in the hashset
                //We could use DateTime.Now as value for LastUsedOn for all sessions, it is within few seconds, but...
                // this causes problems for unit tests for session expiration, when we try to shift current time and see if session is expired;
                // (with current sessions would be updated to shifted time). So we keep actual time (latest) while we accumulate sessions for update
                var query = session.EntitySet <TUserSession>().Where(s => _sessionIds.Contains(s.Id))
                            .Select(s => new { Id = s.Id, LastUsedOn = _lastUsed });

                session.ScheduleNonQuery <TUserSession>(query, Vita.Entities.Linq.LinqCommandType.Update);
            }
示例#19
0
            //Alice defines a utility method to login users.
            public static ILogin Login(IEntitySession session, string userName,
                                       int passwordHash)
            {
                // For simplicity, we use direct LINQ
                var query = from login in session.EntitySet <ILogin>()
                            where login.UserName == userName &&
                            login.PasswordHash == passwordHash
                            select login;
                var logins = query.ToList();

                return(logins.Count == 0 ? null : logins[0]);
            }
示例#20
0
        public static IOAuthRemoteServerAccount GetOAuthAccount(this IEntitySession session, string serverName, string accountName = null)
        {
            if (accountName == null)
            {
                var stt = session.GetOAuthSettings();

                accountName = stt.DefaultAccountName;
            }
            var accountQuery = session.EntitySet <IOAuthRemoteServerAccount>().Where(a => a.Server.Name == serverName && a.Name == accountName);
            var act          = accountQuery.FirstOrDefault();

            return(act);
        }
示例#21
0
        private IBookOrder GetOpenOrder(IEntitySession session, LockType lockType, bool create = false)
        {
            var currUserId = Context.User.UserId;
            var openOrder  = session.EntitySet <IBookOrder>(lockType)
                             .Where(bo => bo.User.Id == currUserId && bo.Status == OrderStatus.Open).FirstOrDefault();

            if (openOrder == null && create)
            {
                var user = session.GetEntity <IUser>(Context.User.UserId);
                openOrder = session.NewOrder(user);
            }
            return(openOrder);
        }
示例#22
0
 public DataHistoryEntry GetEntityOnDate(IEntitySession session, Type entityType, object primaryKey, DateTime onDate)
 {
     Util.Check(primaryKey != null, "Primary key may not be null");
       var entInfo = session.Context.App.Model.GetEntityInfo(entityType);
       Util.Check(entInfo != null, "Type {0} is not registered as an entity.", entityType);
       var entName = entInfo.FullName;
       var entNameHash = Util.StableHash(entName);
       string pkStr = PrimaryKeyAsString(primaryKey);
       var pkHash = Util.StableHash(pkStr);
       var query = session.EntitySet<IDataHistory>().Where(h => h.EntityNameHash == entNameHash && h.EntityName == entName &&
      h.EntityPrimaryKeyHash == pkHash && h.EntityPrimaryKey == pkStr && h.CreatedOn < onDate)
      .OrderByDescending(h => h.CreatedOn);
       var histEnt = query.FirstOrDefault();
       var result = histEnt.ToHistoryEntry(entInfo);
       return result;
 }
        public IOAuthAccessToken GetUserOAuthToken(IEntitySession session, Guid userId, string serverName, string accountName = null)
        {
            accountName = accountName ?? Settings.DefaultAccountName;
            var context     = session.Context;
            var utcNow      = context.App.TimeService.UtcNow;
            var accessToken = session.EntitySet <IOAuthAccessToken>()
                              .Where(t => t.Account.Server.Name == serverName && t.UserId == userId && t.Status == OAuthTokenStatus.Active)
                              .OrderByDescending(t => t.RetrievedOn).FirstOrDefault();

            if (accessToken != null && accessToken.ExpiresOn < utcNow)
            {
                session.UpdateStatus(accessToken.Id, OAuthTokenStatus.Expired); //update directly in db
                return(null);
            }
            return(accessToken);
        }
示例#24
0
        /// <summary>
        /// Creates a search query expression from a predicate and a <c>SearchParams</c> instance, with optional property mapping for ORDER BY clause.
        /// </summary>
        /// <typeparam name="T">Root entity type to be searched.</typeparam>
        /// <param name="session">Entity session.</param>
        /// <param name="where">Search condition.</param>
        /// <param name="searchParams">Search options to be added to the result query: Order-By, Skip, Take. </param>
        /// <param name="nameMapping">Optional, mapping of names in OrderBy list (in searchParams) to actual entity property names. </param>
        /// <param name="options">Optional, search query options.</param>
        /// <returns>Combined search query expression.</returns>
        public static IQueryable <T> CreateSearch <T>(this IEntitySession session,
                                                      Expression <Func <T, bool> > where,
                                                      SearchParams searchParams,
                                                      Dictionary <string, string> nameMapping = null,
                                                      QueryOptions options = QueryOptions.ForceIgnoreCase) where T : class
        {
            var entQuery = session.EntitySet <T>().Where(where).WithOptions(options);

            if (!string.IsNullOrEmpty(searchParams.OrderBy))
            {
                entQuery = entQuery.OrderBy(searchParams.OrderBy, nameMapping);
            }
            // Add Skip, Take
            var result = entQuery.Skip(searchParams.Skip).Take(searchParams.Take);

            return(result);
        }
示例#25
0
        private void SaveModulesInfo(IEntitySession session, DbVersionInfo dbVersion)
        {
            // important - should use EntitySet here; otherwise MySql fails
            var moduleRecs = session.EntitySet <IDbModuleInfo>().ToList();

            foreach (var mi in dbVersion.Modules)
            {
                var mrec = moduleRecs.FirstOrDefault(r => r.ModuleName == mi.ModuleName && r.Schema == mi.Schema);
                if (mrec == null)
                {
                    mrec            = session.NewEntity <IDbModuleInfo>();
                    mrec.ModuleName = mi.ModuleName;
                    mrec.Schema     = mi.Schema;
                }
                mrec.Version = mi.Version.ToString();
            }
        }
示例#26
0
        public DataHistoryEntry GetEntityOnDate(IEntitySession session, Type entityType, object primaryKey, DateTime onDate)
        {
            Util.Check(primaryKey != null, "Primary key may not be null");
            var entInfo = session.Context.App.Model.GetEntityInfo(entityType);

            Util.Check(entInfo != null, "Type {0} is not registered as an entity.", entityType);
            var    entName     = entInfo.FullName;
            var    entNameHash = Util.StableHash(entName);
            string pkStr       = PrimaryKeyAsString(primaryKey);
            var    pkHash      = Util.StableHash(pkStr);
            var    query       = session.EntitySet <IDataHistory>().Where(h => h.EntityNameHash == entNameHash && h.EntityName == entName &&
                                                                          h.EntityPrimaryKeyHash == pkHash && h.EntityPrimaryKey == pkStr && h.CreatedOn < onDate)
                                 .OrderByDescending(h => h.CreatedOn);
            var histEnt = query.FirstOrDefault();
            var result  = histEnt.ToHistoryEntry(entInfo);

            return(result);
        }
示例#27
0
 public static IOAuthRemoteServer CreateOrUpdateServer(IEntitySession session,  string name, OAuthServerOptions options, 
     string siteUrl, string authorizationUrl, string tokenRequestUrl, string tokenRefreshUrl, string scopes,
     string documentationUrl, string basicProfileUrl, string profileUserIdTag)
 {
     IOAuthRemoteServer srv = session.EntitySet<IOAuthRemoteServer>().Where(s => s.Name == name).FirstOrDefault();
       if(srv == null)
     srv = session.NewEntity<IOAuthRemoteServer>();
       srv.Name = name;
       srv.Options = options;
       srv.SiteUrl = siteUrl;
       srv.AuthorizationUrl = authorizationUrl;
       srv.TokenRequestUrl = tokenRequestUrl;
       srv.TokenRefreshUrl = tokenRefreshUrl;
       srv.Scopes = scopes;
       srv.DocumentationUrl = documentationUrl;
       srv.BasicProfileUrl = basicProfileUrl;
       srv.ProfileUserIdTag = profileUserIdTag;
       return srv;
 }
示例#28
0
        /// <summary>Returns a job entity by unique name. </summary>
        /// <param name="session">Entity session.</param>
        /// <param name="jobName">Job name.</param>
        /// <returns>Job entity if found.</returns>
        /// <remarks>Job names does not have to be unique in the database. However, you may create specific reusable jobs with unique names
        /// and lookup them up by name. This method throws exception if a job is not found, or if it finds more than one match.</remarks>
        public static IJob GetJobByUniqueName(this IEntitySession session, string jobName)
        {
            var jobs = session.EntitySet <IJob>().Where(j => j.Name == jobName).Take(2).ToList();

            switch (jobs.Count)
            {
            case 0:
                Util.Check(false, "Job {0} not found.");
                break;

            case 1:
                return(jobs[0]);

            default:
                Util.Check(false, "More than one job found with name '{0}'.", jobName);
                break;
            }
            return(null); //never happens
        }
示例#29
0
        public ILogin GetLogin(IEntitySession session)
        {
            var context = session.Context;
            var user    = context.User;

            context.ThrowIf(user.Kind != UserKind.AuthenticatedUser, ClientFaultCodes.InvalidValue, "User", "User must be authenticated.");
            var query = session.EntitySet <ILogin>();

            if (user.UserId == Guid.Empty)
            {
                query = query.Where(lg => lg.AltUserId == user.AltUserId);
            }
            else
            {
                query = query.Where(lg => lg.UserId == user.UserId);
            }
            var login = query.FirstOrDefault();

            return(login);
        }
示例#30
0
        /// <summary>Returns a list of entities.</summary>
        /// <typeparam name="TEntity">Entity type.</typeparam>
        /// <param name="session">Entity session.</param>
        /// <param name="skip">Optional. A number of entities to skip.</param>
        /// <param name="take">Maximum number of entities to include in results.</param>
        /// <param name="orderBy">Order by expression.</param>
        /// <param name="descending">Descening order flag.</param>
        /// <returns>A list of entities.</returns>
        public static IList <TEntity> GetEntities <TEntity>(this IEntitySession session,
                                                            Expression <Func <TEntity, object> > orderBy = null, bool descending = false,
                                                            int?skip = null, int?take = null) where TEntity : class
        {
            var query = session.EntitySet <TEntity>();

            if (orderBy != null)
            {
                query = descending ? query.OrderByDescending(orderBy) : query.OrderBy(orderBy);
            }
            if (skip != null)
            {
                query = query.Skip(skip.Value);
            }
            if (take != null)
            {
                query = query.Take(take.Value);
            }
            return(query.ToList());
        }
示例#31
0
        //Low-level methods
        public ILogin FindLogin(IEntitySession session, string userName, string password, Guid?tenantId)
        {
            var context = session.Context;

            context.ValidateNotEmpty(userName, ClientFaultCodes.ValueMissing, "UserName", null, "UserName may not be empty");
            context.ValidateNotEmpty(password, ClientFaultCodes.ValueMissing, "Password", null, "Password may not be empty");
            context.ThrowValidation();
            userName = CheckUserName(context, userName);
            var userNameHash  = _hashService.ComputeHash(userName);
            var tenantIdValue = tenantId == null ? Guid.Empty : tenantId.Value;
            var qryLogins     = from lg in session.EntitySet <ILogin>()
                                where lg.UserNameHash == userNameHash && lg.UserName == userName
                                select lg;

            // Match password
            using (session.WithElevatedRead()) {
                var login = qryLogins.FirstOrDefault();
                return(login);
            }
        }
示例#32
0
 public IList<DataHistoryEntry> GetEntityHistory(IEntitySession session, Type entityType, object primaryKey, 
     DateTime? fromDate = null, DateTime? tillDate = null, int skip = 0, int take = 100, Guid? userId = null)
 {
     var entInfo = session.Context.App.Model.GetEntityInfo(entityType);
       Util.Check(entInfo != null, "Type {0} is not registered as an entity.", entityType);
       var entName = entInfo.FullName;
       var entNameHash = Util.StableHash(entName);
       var where = session.NewPredicate<IDataHistory>()
     .And(h => h.EntityNameHash == entNameHash && h.EntityName == entName)
     .AndIfNotEmpty(fromDate, h => h.CreatedOn > fromDate.Value)
     .AndIfNotEmpty(tillDate, h => h.CreatedOn < tillDate.Value);
       if (primaryKey != null) {
     var pkStr = PrimaryKeyAsString(primaryKey);
     var pkHash = Util.StableHash(pkStr);
     where = where.And(h => h.EntityPrimaryKeyHash == pkHash && h.EntityPrimaryKey == pkStr);
       }
       var query = session.EntitySet<IDataHistory>().Where(where).OrderByDescending(h => h.CreatedOn).Skip(skip).Take(take);
       var histEntList = query.ToList();
       var result = histEntList.Select(h => h.ToHistoryEntry(entInfo)).ToList();
       return result;
 }
示例#33
0
        /// <summary>Executes a search query for a given WHERE condition, and returns results object which contains the resulting rows (page)
        /// and total count of rows for a search condition.</summary>
        /// <typeparam name="TEntity">Root entity type.</typeparam>
        /// <param name="session">Entity session.</param>
        /// <param name="where">Combined WHERE condition for a query.</param>
        /// <param name="searchParams">Search parameters object containing extra options for the query: order by, skip, take.</param>
        /// <param name="include">Include expression.</param>
        /// <param name="nameMapping">A name mapping dictionary, to map names in order-by expression to actual properties of the entity.</param>
        /// <param name="options">Optional, search query options.</param>
        /// <returns>An instance of the <c>SearchResults</c> class, with selected rows and total count for the query condition.</returns>
        public static SearchResults <TEntity> ExecuteSearch <TEntity>(
            this IEntitySession session,
            Expression <Func <TEntity, bool> > where,
            SearchParams searchParams,
            Expression <Func <TEntity, object> > include = null,
            Dictionary <string, string> nameMapping      = null,
            QueryOptions options = QueryOptions.ForceIgnoreCase) where TEntity : class
        {
            var baseQuery = session.EntitySet <TEntity>().Where(where).WithOptions(options); //this will be reused by Count query
            //add include, order by, skip, take
            var incQuery     = include == null ? baseQuery : baseQuery.Include <TEntity>(include);
            var orderedQuery = string.IsNullOrEmpty(searchParams.OrderBy) ? incQuery : incQuery.OrderBy(searchParams.OrderBy, nameMapping);
            // Add Skip, Take; we return '+1' rows, to check if there are any more; if not, we do not need to query total
            var takePlusOne = searchParams.Take + 1;
            var pageQuery   = orderedQuery.Skip(searchParams.Skip).Take(takePlusOne);
            var rows        = pageQuery.ToList();

            if (rows.Count < takePlusOne)
            {
                //We see the last row, we do not need to run total query
                return new SearchResults <TEntity>()
                       {
                           Results = rows, TotalCount = searchParams.Skip + rows.Count
                       }
            }
            ;
            // we received more than Take number of rows; it means we need to run TotalCount
            //save main query command, and restore it after total query; in debugging main query is more interesting than total query
            var queryCmd   = session.GetLastCommand();
            var totalCount = baseQuery.Count(); //use baseQuery here, without OrderBy, Skip, Take

            session.SetLastCommand(queryCmd);   //restore main query command
            rows.RemoveAt(rows.Count - 1);      //remove last extra row
            var results = new SearchResults <TEntity>()
            {
                Results = rows, TotalCount = totalCount
            };

            return(results);
        }
示例#34
0
        public static SearchResults <Book> SearchBooks(this IEntitySession session, BookSearch searchParams)
        {
            // Warning about substring match (LIKE): Be careful using it in real apps, against big tables
            // Match by fragment results in LIKE operator which NEVER works on real volumes.
            // For MS SQL, it is OK to do LIKE with pattern that does not start with % (so it is StartsWith(smth) operator).
            //  AND column must be indexed - so server will use index. For match inside the string, LIKE is useless on big tables.
            // In our case, Title is indexed and we use StartsWith, so it's OK
            // An interesting article about speeding up string-match search in MS SQL:
            //  http://aboutsqlserver.com/2015/01/20/optimizing-substring-search-performance-in-sql-server/
            var categories = ConvertHelper.ParseEnumArray <BookCategory>(searchParams.Categories);

            var where = session.NewPredicate <IBook>()
                        .AndIfNotEmpty(searchParams.Title, b => b.Title.StartsWith(searchParams.Title))
                        .AndIfNotEmpty(searchParams.MaxPrice, b => b.Price <= (Decimal)searchParams.MaxPrice.Value)
                        .AndIfNotEmpty(searchParams.Publisher, b => b.Publisher.Name.StartsWith(searchParams.Publisher))
                        .AndIfNotEmpty(searchParams.PublishedAfter, b => b.PublishedOn.Value >= searchParams.PublishedAfter.Value)
                        .AndIfNotEmpty(searchParams.PublishedBefore, b => b.PublishedOn.Value <= searchParams.PublishedBefore.Value)
                        .AndIf(categories != null && categories.Length > 0, b => categories.Contains(b.Category));
            // A bit more complex clause for Author - it is many2many, results in subquery
            if (!string.IsNullOrEmpty(searchParams.AuthorLastName))
            {
                var qAuthBookIds = session.EntitySet <IBookAuthor>()
                                   .Where(ba => ba.Author.LastName.StartsWith(searchParams.AuthorLastName))
                                   .Select(ba => ba.Book.Id);
                where = where.And(b => qAuthBookIds.Contains(b.Id));
            }
            // Alternative method for author name - results in inefficient query (with subquery for every row)
            //      if(!string.IsNullOrEmpty(authorLastName))
            //         where = where.And(b => b.Authors.Any(a => a.LastName == authorLastName));

            //Use VITA-defined helper method ExecuteSearch - to build query from where predicate, get total count,
            // add clauses for OrderBy, Take, Skip, run query and convert to list of model objects with TotalCount

            var results = session.ExecuteSearch(where, searchParams, ibook => ibook.ToModel(), b => b.Publisher,
                                                nameMapping: _orderByMapping);

            return(results);
        }
示例#35
0
        //For now implemented using dynamically built LINQ query; stored proc support to come later
        // TODO: save filter Func in EntityInfo and reuse it
        public static TEntity GetEntity <TEntity>(this IEntitySession session, object primaryKey, LockOptions options)
            where TEntity : class
        {
            if (options == LockOptions.None)
            {
                return(session.GetEntity <TEntity>(primaryKey)); //short path, no locks
            }
            session.LogMessage("-- Locking entity {0}/{1}", typeof(TEntity).Name, primaryKey);
            var entInfo   = session.Context.App.Model.GetEntityInfo(typeof(TEntity), throwIfNotFound: true);
            var pkMembers = entInfo.PrimaryKey.KeyMembers;

            Util.Check(pkMembers.Count == 1, "Cannot lock entity {0}: composite primary keys not supported.", entInfo.Name);
            var pkMember = entInfo.PrimaryKey.KeyMembers[0].Member;
            var prmEnt   = Expression.Parameter(typeof(TEntity), "e");
            var pkRead   = Expression.MakeMemberAccess(prmEnt, pkMember.ClrMemberInfo);
            var eq       = Expression.Equal(pkRead, Expression.Constant(primaryKey, pkMember.DataType));
            var filter   = Expression.Lambda <Func <TEntity, bool> >(eq, prmEnt);
            var query    = session.EntitySet <TEntity>(options).Where(filter);
            // We use ToList() on entire query instead of First() because we have already filter on PK value,
            // and we want to avoid adding any paging (skip/take) clauses to the SQL.
            // We use FirstOrDefult on entire list, and check that we got something; if not, we throw clear message.
            var ent = query.ToList().FirstOrDefault();

            Util.Check(ent != null, "Entity {0} with ID {1} does not exist, cannot set the lock.", entInfo.EntityType.Name,
                       primaryKey);
            return(ent);

            /*
             * //The following is just a sketch
             * if (checkLastModifiedId != null) {
             * Util.Check(entInfo.VersioningMember != null, "Entity {0} has no tracking/versioning column (last modified transaction id), cannot check data version.", entInfo.Name);
             * var lastTransId = EntityHelper.GetProperty<Guid>(ent, entInfo.VersioningMember.MemberName);
             * session.Context.ThrowIf(doNotUse_checkLastModifiedId.Value != lastTransId, ClientFaultCodes.ConcurrentUpdate, entInfo.VersioningMember.MemberName, "Entity {0} was modified by concurrent process.", entInfo.Name);
             * }
             * */
        }
示例#36
0
 //Low-level methods
 public ILogin FindLogin(IEntitySession session, string userName, string password, Guid? tenantId)
 {
     var context = session.Context;
       context.ValidateNotEmpty(userName, ClientFaultCodes.ValueMissing, "UserName", null, "UserName may not be empty");
       context.ValidateNotEmpty(password, ClientFaultCodes.ValueMissing, "Password", null, "Password may not be empty");
       context.ThrowValidation();
       userName = CheckUserName(context, userName);
       var userNameHash = Util.StableHash(userName);
       var weakPwdHash = GetWeakPasswordHash(password);
       var tenantIdValue = tenantId == null ? Guid.Empty : tenantId.Value;
       // Note: we do not compare usernames, only UserNameHash values; UserName might be null if we don't save them
       var qryLogins = from lg in session.EntitySet<ILogin>()
               where lg.UserNameHash == userNameHash && lg.WeakPasswordHash == weakPwdHash
                 && lg.TenantId == tenantIdValue
               select lg;
       //Query logins table
       using(session.WithElevateRead()) {
     var logins = qryLogins.ToList(); //these are candidates, but most often will be just one
     var login = logins.FirstOrDefault(lg => VerifyPassword(lg, password));
     if(login != null)
       VerifyExpirationSuspensionDates(login);
     return login;
       }
 }
示例#37
0
 private IBookOrder GetOpenOrder(IEntitySession session, LockOptions lockOptions, bool create = false)
 {
     var currUserId = Context.User.UserId;
       var openOrder = session.EntitySet<IBookOrder>(lockOptions)
     .Where(bo => bo.User.Id == currUserId && bo.Status == OrderStatus.Open).FirstOrDefault();
       if (openOrder == null && create) {
     var user = session.GetEntity<IUser>(Context.User.UserId);
     openOrder = session.NewOrder(user);
       }
       return openOrder;
 }
示例#38
0
 public IList<ISecretQuestion> GetAllSecretQuestions(IEntitySession session)
 {
     var mask = SecretQuestionFlags.Disabled | SecretQuestionFlags.Private;
       var query = from q in session.EntitySet<ISecretQuestion>()
           where (q.Flags & mask) == 0 //we look for public and enabled
           orderby q.Number
           select q;
       var questions = query.ToList();
       return questions;
 }
示例#39
0
 public ILogin GetLogin(IEntitySession session)
 {
     var context = session.Context;
       var user = context.User;
       context.ThrowIf(user.Kind != UserKind.AuthenticatedUser, ClientFaultCodes.InvalidValue, "User", "User must be authenticated.");
       var query = session.EntitySet<ILogin>();
       if(user.UserId == Guid.Empty)
     query = query.Where(lg => lg.AltUserId == user.AltUserId);
       else
     query = query.Where(lg => lg.UserId == user.UserId);
       var login = query.FirstOrDefault();
       return login;
 }