public void Save(AccessKey accessKey)
        {
            if (accessKey == null)
                throw new ArgumentNullException("accessKey");

            using (var context = new DeviceHiveContext())
            {
                context.AccessKeys.Add(accessKey);
                if (accessKey.ID > 0)
                {
                    context.Entry(accessKey).State = EntityState.Modified;
                    
                    foreach (var permission in accessKey.Permissions.Where(e => e.ID > 0))
                    {
                        context.Entry(permission).State = EntityState.Modified;
                    }
                    foreach (var permission in context.AccessKeyPermissions.Where(e => e.AccessKeyID == accessKey.ID))
                    {
                        if (context.Entry(permission).State == EntityState.Unchanged)
                            context.AccessKeyPermissions.Remove(permission);
                    }
                }
                
                context.SaveChanges();
            }
        }
        /// <summary>
        /// Initializes all required properties.
        /// </summary>
        /// <param name="client">Associated OAuthClient object.</param>
        /// <param name="userId">Associated user identifier.</param>
        /// <param name="accessKey">Associated AccessKey object.</param>
        /// <param name="type">OAuth type.</param>
        /// <param name="scope">Requested OAuth scope.</param>
        public OAuthGrant(OAuthClient client, int userId, AccessKey accessKey, int type, string scope)
        {
            if (client == null)
                throw new ArgumentNullException("client");
            if (accessKey == null)
                throw new ArgumentNullException("accessKey");
            if (string.IsNullOrEmpty(scope))
                throw new ArgumentException("Scope is null or empty!", "scope");

            this.Timestamp = DateTime.UtcNow;
            this.Client = client;
            this.UserID = userId;
            this.AccessKey = accessKey;
            this.Type = type;
            this.Scope = scope;
        }
        public void Save(AccessKey accessKey)
        {
            if (accessKey == null)
                throw new ArgumentNullException("accessKey");

            _mongo.EnsureIdentity(accessKey);

            if (accessKey.Permissions == null)
                accessKey.Permissions = new List<AccessKeyPermission>();
            accessKey.Permissions.ForEach(e => _mongo.EnsureIdentity(e));

            _mongo.AccessKeys.Save(accessKey);

            _mongo.OAuthGrants.Update(Query<OAuthGrant>.EQ(e => e.AccessKeyID, accessKey.ID),
                Update<OAuthGrant>.Set(e => e.AccessKey, accessKey), new MongoUpdateOptions { Flags = UpdateFlags.Multi });
        }
        public void Authenticate()
        {
            if (ActionContext.GetParameter("AuthUser") == null)
                throw new WebSocketRequestException("Please specify 'login' and 'password' or 'accessKey'");

            CurrentUser = (User)ActionContext.GetParameter("AuthUser");
            CurrentAccessKey = (AccessKey)ActionContext.GetParameter("AuthAccessKey");

            SendSuccessResponse();
        }
        public void OAuthGrant()
        {
            var user = new User("Test", 0, 0);
            user.SetPassword("pass");
            DataContext.User.Save(user);
            RegisterTearDown(() => DataContext.User.Delete(user.ID));

            var accessKey = new AccessKey(user.ID, AccessKeyType.OAuth, "test");
            DataContext.AccessKey.Save(accessKey);
            RegisterTearDown(() => DataContext.AccessKey.Delete(accessKey.ID));

            var client = new OAuthClient("Test", "test.com", "http://test.com/oauth2", "test_client");
            DataContext.OAuthClient.Save(client);
            RegisterTearDown(() => DataContext.OAuthClient.Delete(client.ID));

            var grant = new OAuthGrant(client, user.ID, accessKey, 0, "scope");
            grant.AuthCode = Guid.NewGuid();
            DataContext.OAuthGrant.Save(grant);
            RegisterTearDown(() => DataContext.OAuthGrant.Delete(grant.ID));

            // test GetByUser
            var grants = DataContext.OAuthGrant.GetByUser(user.ID);
            Assert.Greater(grants.Count, 0);

            // test Get(id)
            var grant1 = DataContext.OAuthGrant.Get(grant.ID);
            Assert.IsNotNull(grant1);
            Assert.Less(Math.Abs(DateTime.UtcNow.Subtract(grant1.Timestamp).TotalMinutes), 10);
            Assert.AreEqual(0, grant1.Type);
            Assert.AreEqual("scope", grant1.Scope);
            Assert.AreEqual(client.ID, grant1.ClientID);
            Assert.IsNotNull(grant1.Client);
            Assert.AreEqual(user.ID, grant1.UserID);
            Assert.AreEqual(accessKey.ID, grant1.AccessKeyID);
            Assert.IsNotNull(grant1.AccessKey);

            // test Get(authCode)
            var grant2 = DataContext.OAuthGrant.Get(grant.AuthCode.Value);
            Assert.IsNotNull(grant2);
            Assert.AreEqual(0, grant2.Type);
            Assert.AreEqual("scope", grant2.Scope);
            Assert.AreEqual(user.ID, grant2.UserID);
            Assert.AreEqual(client.ID, grant2.ClientID);
            Assert.IsNotNull(grant2.Client);
            Assert.AreEqual(accessKey.ID, grant2.AccessKeyID);
            Assert.IsNotNull(grant2.AccessKey);

            // test Save
            grant.AuthCode = Guid.NewGuid();
            grant.Type = 1;
            grant.AccessType = 1;
            grant.RedirectUri = "http://test.com/oauth";
            grant.Scope = "scope scope2";
            grant.Networks = new[] { 5, 10 };
            DataContext.OAuthGrant.Save(grant);
            var grant3 = DataContext.OAuthGrant.Get(grant.ID);
            Assert.AreEqual(grant.AuthCode, grant3.AuthCode);
            Assert.AreEqual(1, grant3.Type);
            Assert.AreEqual(1, grant3.AccessType);
            Assert.AreEqual("http://test.com/oauth", grant3.RedirectUri);
            Assert.AreEqual("scope scope2", grant3.Scope);
            Assert.AreEqual(2, grant3.Networks.Length);
            Assert.AreEqual(5, grant3.Networks[0]);
            Assert.AreEqual(10, grant3.Networks[1]);
            Assert.AreEqual(user.ID, grant3.UserID);
            Assert.AreEqual(client.ID, grant3.ClientID);
            Assert.IsNotNull(grant3.Client);
            Assert.AreEqual(accessKey.ID, grant3.AccessKeyID);
            Assert.IsNotNull(grant3.AccessKey);

            // test update relationship
            var client2 = new OAuthClient("Test2", "test2.com", "http://test.com/oauth/2", "test_client2");
            DataContext.OAuthClient.Save(client2);
            RegisterTearDown(() => DataContext.OAuthClient.Delete(client2.ID));
            grant.Client = client2;
            DataContext.OAuthGrant.Save(grant);
            var grant4 = DataContext.OAuthGrant.Get(grant.ID);
            Assert.AreEqual(client2.ID, grant4.ClientID);
            Assert.IsNotNull(grant4.Client);

            // test Delete
            DataContext.OAuthClient.Delete(grant.ID);
            var grant5 = DataContext.OAuthClient.Get(grant.ID);
            Assert.IsNull(grant5);
        }
        public void AccessKey()
        {
            var user = new User("Test", (int)UserRole.Administrator, (int)UserStatus.Active);
            user.SetPassword("TestPass");
            DataContext.User.Save(user);
            RegisterTearDown(() => DataContext.User.Delete(user.ID));

            var accessKey = new AccessKey(user.ID, AccessKeyType.Default, "Test");
            accessKey.Permissions.Add(new AccessKeyPermission { Subnets = new[] { "127.0.0.1" } });
            accessKey.Permissions.Add(new AccessKeyPermission { Subnets = new[] { "127.0.0.2" } });
            DataContext.AccessKey.Save(accessKey);
            RegisterTearDown(() => DataContext.AccessKey.Delete(accessKey.ID));

            // test GetByUser
            var accessKeys = DataContext.AccessKey.GetByUser(user.ID);
            Assert.AreEqual(1, accessKeys.Count);
            Assert.AreEqual(accessKey.ID, accessKeys[0].ID);
            Assert.AreEqual(user.ID, accessKeys[0].UserID);

            // test GetByUsers
            accessKeys = DataContext.AccessKey.GetByUsers(new[] { user.ID }, new AccessKeyFilter { Type = (int)AccessKeyType.Default });
            Assert.AreEqual(1, accessKeys.Count);
            Assert.AreEqual(accessKey.ID, accessKeys[0].ID);
            Assert.AreEqual(user.ID, accessKeys[0].UserID);

            // test Get(id)
            var accessKey1 = DataContext.AccessKey.Get(accessKey.ID);
            Assert.IsNotNull(accessKey1);
            Assert.AreEqual("Test", accessKey1.Label);
            Assert.AreEqual(accessKey.Key, accessKey1.Key);
            Assert.IsNotNull(accessKey1.Permissions);
            Assert.AreEqual(2, accessKey1.Permissions.Count);
            Assert.AreEqual(new[] { "127.0.0.1" }, accessKey1.Permissions[0].Subnets);
            Assert.AreEqual(new[] { "127.0.0.2" }, accessKey1.Permissions[1].Subnets);

            // test Save
            accessKey.Type = (int)AccessKeyType.Session;
            accessKey.Label = "Test2";
            accessKey.GenerateKey();
            accessKey.ExpirationDate = DateTime.UtcNow;
            accessKey.Permissions.RemoveAt(1);
            accessKey.Permissions.Add(new AccessKeyPermission {
                Subnets = new[] { "127.0.0.3" },
                Domains = new[] { "www.example.com" },
                Networks = new[] { 1, 2, 3 }});
            DataContext.AccessKey.Save(accessKey);
            var accessKey2 = DataContext.AccessKey.Get(accessKey.ID);
            Assert.AreEqual(1, accessKey2.Type);
            Assert.AreEqual("Test2", accessKey2.Label);
            Assert.AreEqual(accessKey.Key, accessKey2.Key);
            Assert.IsNotNull(accessKey2.ExpirationDate);
            Assert.IsNotNull(accessKey2.Permissions);
            Assert.AreEqual(2, accessKey2.Permissions.Count);
            Assert.AreEqual(new[] { "127.0.0.1" }, accessKey2.Permissions[0].Subnets);
            Assert.AreEqual(new[] { "127.0.0.3" }, accessKey2.Permissions[1].Subnets);
            Assert.AreEqual(new[] { "www.example.com" }, accessKey2.Permissions[1].Domains);
            Assert.AreEqual(new[] { 1, 2, 3 }, accessKey2.Permissions[1].Networks);

            // test Delete
            DataContext.AccessKey.Delete(accessKey.ID);
            var accessKey3 = DataContext.AccessKey.Get(accessKey.ID);
            Assert.IsNull(accessKey3);
        }
        private AccessKey CreateAccessKey(User user)
        {
            const string Label = "Session Token";

            var accessKey = new AccessKey(user.ID, AccessKeyType.Session, Label);
            accessKey.Permissions = new List<AccessKeyPermission>();
            accessKey.Permissions.Add(new AccessKeyPermission()); // allow everything permission
            accessKey.ExpirationDate = DateTime.UtcNow.Add(DeviceHiveConfiguration.Authentication.SessionTimeout);

            DataContext.AccessKey.Save(accessKey);
            return accessKey;
        }