Example #1
0
        public static XDoc GetGroupXmlVerbose(GroupBE group, string relation)
        {
            XDoc groupXml = GetGroupXml(group, relation);

            ServiceBE authService = ServiceBL.GetServiceById(group.ServiceId);

            if (authService != null)
            {
                groupXml.Add(ServiceBL.GetServiceXml(authService, "authentication"));
            }

            groupXml.Start("users");
            if (group.UserIdsList != null)
            {
                groupXml.Attr("count", group.UserIdsList.Length);
            }

            groupXml.Attr("href", DekiContext.Current.ApiUri.At("groups", group.Id.ToString(), "users"));
            groupXml.End();

            //Permissions for the group
            RoleBE role = PermissionsBL.GetRoleById(group.RoleId);

            groupXml.Add(PermissionsBL.GetRoleXml(role, "group"));
            return(groupXml);
        }
        public Yield GetServiceById(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            bool privateDetails = PermissionsBL.IsUserAllowed(DekiContext.Current.User, Permissions.ADMIN);

            //Private feature requires api-key
            var  identifier = context.GetParam("id");
            uint serviceId  = 0;

            if (identifier.StartsWith("="))
            {
                var serviceInfo = DekiContext.Current.Instance.RunningServices[XUri.Decode(identifier.Substring(1))];
                if (serviceInfo != null)
                {
                    serviceId = serviceInfo.ServiceId;
                }
            }
            else
            {
                if (!uint.TryParse(identifier, out serviceId))
                {
                    throw new DreamBadRequestException(string.Format("Invalid id '{0}'", identifier));
                }
            }
            ServiceBE service = ServiceBL.GetServiceById(serviceId);

            if (service == null)
            {
                throw new ServiceNotFoundException(identifier);
            }
            response.Return(DreamMessage.Ok(ServiceBL.GetServiceXmlVerbose(DekiContext.Current.Instance, service, null, privateDetails)));
            yield break;
        }
Example #3
0
        private static ServiceBE NewServiceFromXml(XDoc serviceDoc, string SID, string description, bool?statusEnabled,
                                                   bool?localInit, ServiceType?type, string uri, NameValueCollection config, NameValueCollection preferences)
        {
            ServiceBE service = new ServiceBE();

            if (string.IsNullOrEmpty(SID) && (localInit ?? true))
            {
                throw new ServiceMissingCreateSIDInvalidOperationException();
            }

            if (type == null || type == ServiceType.UNDEFINED)
            {
                throw new ServiceMissingCreateTypeInvalidArgumentException();
            }

            service.SID             = SID ?? string.Empty;
            service.Description     = description ?? string.Empty;
            service.ServiceEnabled  = statusEnabled ?? true;
            service.ServiceLocal    = localInit ?? true;
            service.Type            = type.Value;
            service.Uri             = uri ?? string.Empty;
            service.Preferences     = preferences ?? new NameValueCollection();
            service.Config          = config ?? new NameValueCollection();
            service.ServiceLastEdit = DateTime.UtcNow;

            return(service);
        }
        internal Yield PostServicesId(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            ServiceBL.EnsureServiceAdministrationAllowed();
            uint      id      = context.GetParam <uint>("id");
            ServiceBE service = DbUtils.CurrentSession.Services_GetById(id);

            if (service == null)
            {
                throw new ServiceNotFoundException(id);
            }
            if (context.Verb.EqualsInvariantIgnoreCase("PUT"))
            {
                //Modify a service (only with PUT)
                service = ServiceBL.PostServiceFromXml(request.ToDocument(), service);
                response.Return(DreamMessage.Ok(ServiceBL.GetServiceXmlVerbose(DekiContext.Current.Instance, service, null)));
            }
            else
            {
                //Backward compatibility: posting an empty document restarts the service
                service = ServiceBL.StartService(service, true, true);
                if (service.ServiceEnabled && (service.Uri == null))
                {
                    throw new ServiceSettingsInvalidArgumentException();
                }
                response.Return(DreamMessage.Ok(ServiceBL.GetServiceXmlVerbose(DekiContext.Current.Instance, service, null)));
            }
            yield break;
        }
Example #5
0
        public static ServiceBE UpdateService(ServiceBE service)
        {
            DbUtils.CurrentSession.Services_Delete(service.Id);
            uint serviceId = DbUtils.CurrentSession.Services_Insert(service);

            // reload the service
            return(DbUtils.CurrentSession.Services_GetById(serviceId));
        }
Example #6
0
        public static XDoc GetServiceXml(ServiceBE service, string relation)
        {
            XDoc serviceXml = new XDoc(string.IsNullOrEmpty(relation) ? "service" : "service." + relation);

            serviceXml.Attr("id", service.Id);
            serviceXml.Attr("href", DekiContext.Current.ApiUri.At("site", "services", service.Id.ToString()));
            return(serviceXml);
        }
Example #7
0
        public static bool IsLocalAuthService(ServiceBE service)
        {
            if (service == null)
            {
                return(false);
            }

            return(service.Id == BUILT_IN_AUTH_SERVICE_ID);
        }
Example #8
0
        private static ServiceBE StopService(uint serviceId, ServiceBE service, ServiceStopType stopType)
        {
            if (IsLocalAuthService(serviceId))
            {
                return(service);
            }
            DekiContext context = DekiContext.Current;
            bool        saveBe  = false;

            if (service != null && service.ServiceLocal)
            {
                // local services should have their uri cleared out
                _log.DebugFormat("stopping service '{0}'", service.SID);
                service.Uri = null;
                saveBe      = true;
            }
            if (service != null && stopType == ServiceStopType.Disable)
            {
                // wipe out last error on disable
                service.ServiceLastStatus = null;
                saveBe = true;
            }
            var serviceInfo = context.Instance.RunningServices[serviceId];

            if (serviceInfo == null)
            {
                if (saveBe)
                {
                    service = UpdateService(service) ?? service;
                }

                // service is not registered as running, we're done here
                return(service);
            }

            try {
                context.Instance.DeregisterService(serviceId);
            } catch (Exception e) {
                // log the error, but ignore it otherwise
                if (service == null)
                {
                    context.Instance.Log.WarnExceptionMethodCall(e, "StopService", string.Format("Unable to stop {0} service id '{1}'", serviceInfo.IsLocal ? "local" : "remote", serviceId));
                }
                else
                {
                    context.Instance.Log.WarnExceptionMethodCall(e, "StopService", string.Format("Unable to stop {0} service id '{1}' with SID '{2}'", serviceInfo.IsLocal ? "local" : "remote", serviceId, service.SID));
                }
            }

            if (service != null && (stopType == ServiceStopType.Disable || saveBe))
            {
                service.ServiceEnabled = (stopType != ServiceStopType.Disable);
                service = UpdateService(service) ?? service;
            }
            return(service);
        }
        //--- Methods ---
        public IServiceInfo RegisterService(ServiceBE service, XUri serviceUri, bool isLocal)
        {
            var serviceInfo = new ServiceInfo(this, service.Id, serviceUri, isLocal);

            lock (_servicesById) {
                _servicesById[service.Id]  = serviceInfo;
                _servicesByUri[serviceUri] = serviceInfo;
                RegisterNamespace(serviceInfo, service.Preferences["namespace"]);
            }
            return(serviceInfo);
        }
Example #10
0
        private IList <ServiceBE> Services_Populate(IDataReader dr)
        {
            // read all services
            List <ServiceBE>             orderedServiceList = new List <ServiceBE>();
            Dictionary <uint, ServiceBE> result             = new Dictionary <uint, ServiceBE>();
            ServiceBE s = null;

            while (dr.Read())
            {
                s = new ServiceBE();
                s._ServiceEnabled = dr.Read <byte>("service_enabled");
                s._ServiceLocal   = dr.Read <byte>("service_local");
                s.Description     = dr.Read <string>("service_description");
                s.Id = dr.Read <uint>("service_id");
                s.ServiceLastEdit   = dr.Read <DateTime>("service_last_edit");
                s.ServiceLastStatus = dr.Read <string>("service_last_status");
                s.SID  = dr.Read <string>("service_sid");
                s.Type = dr.Read <ServiceType>("service_type");
                s.Uri  = dr.Read <string>("service_uri");

                result.Add(s.Id, s);
                orderedServiceList.Add(s);
            }

            // read config key/value pairs for each service
            dr.NextResult();
            while (dr.Read())
            {
                uint serviceId = DbUtils.Convert.To <uint>(dr["service_id"], 0);
                if (serviceId != 0 && result.ContainsKey(serviceId))
                {
                    s = result[serviceId];
                    string config_name  = DbUtils.Convert.To <string>(dr["config_name"], "");
                    string config_value = DbUtils.Convert.To <string>(dr["config_value"], "");
                    s.Config[config_name] = config_value;
                }
            }

            //  read preference key/value pairs for each service
            dr.NextResult();
            while (dr.Read())
            {
                uint serviceId = DbUtils.Convert.To <uint>(dr["service_id"], 0);
                if (serviceId != 0 && result.ContainsKey(serviceId))
                {
                    s = result[serviceId];
                    string pref_name  = DbUtils.Convert.To <string>(dr["pref_name"], "");
                    string pref_value = DbUtils.Convert.To <string>(dr["pref_value"], "");
                    s.Preferences[pref_name] = pref_value;
                }
            }

            return(orderedServiceList);
        }
Example #11
0
        public static void DeleteService(ServiceBE service)
        {
            if (IsLocalAuthService(service))
            {
                throw new ServiceCannotDeleteAuthInvalidOperationException();
            }

            service = StopService(service);
            DbUtils.CurrentSession.Services_Delete(service.Id);
            DbUtils.CurrentSession.Users_UpdateServicesToLocal(service.Id);
            DbUtils.CurrentSession.Groups_UpdateServicesToLocal(service.Id);
        }
Example #12
0
        public static ServiceBE RetrieveLocalAuthService()
        {
            //TODO (MaxM): This can be fixed by changing the service_type for the local auth service to uniquely find it.

            ServiceBE service = GetServiceById(BUILT_IN_AUTH_SERVICE_ID);

            if (!StringUtil.EqualsInvariantIgnoreCase(service.SID.Trim(), SID_FOR_LOCAL))
            {
                throw new ServiceSIDExpectedFatalException(SID_FOR_LOCAL);
            }
            return(service);
        }
        internal Yield PostServiceIdStop(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            ServiceBL.EnsureServiceAdministrationAllowed();
            uint id = context.GetParam <uint>("id");

            ServiceBE service = ServiceBL.StopService(id, false);

            if (service == null)
            {
                throw new ServiceNotFoundException(id);
            }
            response.Return(DreamMessage.Ok(ServiceBL.GetServiceXmlVerbose(DekiContext.Current.Instance, service, null)));
            yield break;
        }
Example #14
0
 private static void ValidateGroupMemberList(ServiceBE groupService, UserBE[] potentialMembers)
 {
     //Groups belonging to built-in auth service are allowed to contain users from remote services
     if (!ServiceBL.IsLocalAuthService(groupService))
     {
         foreach (UserBE u in potentialMembers)
         {
             if (u.ServiceId != groupService.Id)
             {
                 throw new GroupMembersRequireSameAuthInvalidOperationException();
             }
         }
     }
 }
Example #15
0
        public static ServiceBE PostServiceFromXml(XDoc serviceDoc, ServiceBE serviceToProcess)
        {
            uint?               serviceId;
            string              SID, description, uri;
            bool?               statusEnabled;
            bool?               localInit;
            ServiceType?        type;
            NameValueCollection config, preferences;

            ParseServiceXml(serviceDoc, out serviceId, out SID, out description, out statusEnabled, out localInit, out type, out uri, out config, out preferences);

            //new service
            if (serviceToProcess == null && (serviceId == null || serviceId == 0))
            {
                //convert XML input to a service object
                serviceToProcess = NewServiceFromXml(serviceDoc, SID, description, statusEnabled, localInit, type, uri, config, preferences);

                //insert the service
                serviceId = DbUtils.CurrentSession.Services_Insert(serviceToProcess);

                // reload the service
                serviceToProcess = DbUtils.CurrentSession.Services_GetById(serviceId.Value);
            }
            else
            {
                //Validate logic of given xml
                if (ServiceBL.IsLocalAuthService(serviceToProcess))
                {
                    throw new ServiceCannotModifyBuiltInAuthInvalidOperationException();
                }

                if (((uri ?? string.Empty) != string.Empty) && (localInit ?? false))
                {
                    throw new ServiceCannotSetLocalUriInvalidOperationException();
                }

                //Stop the service before making any changes
                serviceToProcess = StopService(serviceToProcess);

                //convert XML input to a service object.
                serviceToProcess = UpdateServiceFromParsedXml(serviceToProcess, SID, description, statusEnabled, localInit, type, uri, config, preferences);

                //Update existing service
                serviceToProcess = UpdateService(serviceToProcess);
            }

            return(serviceToProcess);
        }
        internal Yield DeleteSiteService(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            ServiceBL.EnsureServiceAdministrationAllowed();

            uint      id      = context.GetParam <uint>("id");
            ServiceBE service = DbUtils.CurrentSession.Services_GetById(id);

            if (service == null)
            {
                throw new ServiceNotFoundException(id);
            }

            ServiceBL.DeleteService(service);
            response.Return(DreamMessage.Ok());
            yield break;
        }
Example #17
0
        private static ServiceBE UpdateServiceFromParsedXml(ServiceBE service, string SID, string description, bool?statusEnabled, bool?localInit,
                                                            ServiceType?type, string uri, NameValueCollection config, NameValueCollection preferences)
        {
            //Modify only changed (non-null) values

            if (SID != null)
            {
                service.SID = SID;
            }

            if (service.Description != null)
            {
                service.Description = description;
            }

            if (statusEnabled != null)
            {
                service.ServiceEnabled = statusEnabled.Value;
            }

            if (localInit != null)
            {
                service.ServiceLocal = localInit.Value;
            }

            if (type != null && type.Value != ServiceType.UNDEFINED)
            {
                service.Type = type.Value;
            }

            if (uri != null)
            {
                service.Uri = uri;
            }

            if (config != null)
            {
                service.Config = config;
            }

            if (preferences != null)
            {
                service.Preferences = preferences;
            }

            return(service);
        }
Example #18
0
        public static void InsertDWService(ServiceBE service)
        {
            DataCommand cmd = MediaWikiConverterContext.Current.DWCatalog.NewQuery(String.Format("INSERT into services (service_type, service_sid, service_description, service_local, service_enabled) VALUES ('{0}', '{1}', '{2}', '{3}', '{4}'); SELECT LAST_INSERT_ID() as serviceid;",
                                                                                                 service.Type.ToString().ToLowerInvariant(), DataCommand.MakeSqlSafe(service.SID), DataCommand.MakeSqlSafe(service.Description), service._ServiceLocal, service._ServiceEnabled));

            cmd.Execute(delegate(IDataReader dr) {
                while (dr.Read())
                {
                    service.Id = DbUtils.Convert.To <uint>(dr["serviceid"], 0);
                }
            });
            foreach (String key in service.Config.Keys)
            {
                MediaWikiConverterContext.Current.DWCatalog.NewQuery(String.Format("INSERT into service_config (service_id, config_name, config_value) VALUES ('{0}', '{1}', '{2}')",
                                                                                   service.Id, DataCommand.MakeSqlSafe(key), DataCommand.MakeSqlSafe(service.Config[key]))).Execute();
            }
        }
Example #19
0
        public static XDoc GetServiceXmlVerbose(DekiInstance instance, ServiceBE service, string relation, bool privateDetails)
        {
            XDoc serviceXml = GetServiceXml(service, relation);

            serviceXml.Start("sid").Value(service.SID ?? string.Empty).End();

            serviceXml.Start("uri").Value(XUri.TryParse(service.Uri)).End();

            serviceXml.Start("type").Value(service.Type.ToString().ToLowerInvariant()).End();
            serviceXml.Start("description").Value(service.Description ?? "").End();

            serviceXml.Elem("date.modified", service.ServiceLastEdit);
            serviceXml.Elem("status", service.ServiceEnabled ? "enabled" : "disabled");

            serviceXml.Start("local").Value(service.ServiceLocal).Attr("deprecated", true).End();
            serviceXml.Elem("init", service.ServiceLocal ? "native" : "remote");
            var serviceInfo = instance.RunningServices[service.Id];

            if (serviceInfo != null && !string.IsNullOrEmpty(serviceInfo.Namespace))
            {
                serviceXml.Elem("namespace", serviceInfo.Namespace);
            }
            if (privateDetails)
            {
                serviceXml.Elem("lasterror", service.ServiceLastStatus ?? "");

                serviceXml.Start("config");

                foreach (string key in service.Config.AllKeys)
                {
                    serviceXml.Start("value").Attr("key", key).Value(service.Config[key]).End();
                }
                serviceXml.End();

                serviceXml.Start("preferences");
                foreach (string key in service.Preferences.AllKeys)
                {
                    serviceXml.Start("value").Attr("key", key).Value(service.Preferences[key]).End();
                }
                serviceXml.End();
            }
            return(serviceXml);
        }
Example #20
0
        public IList <PermissionBE> GetServicePermissions(ServiceBE service)
        {
            var     dbContext = new DBContext();
            DataSet dataSet;


            var permissions = new List <PermissionBE>();

            var parameters = new SqlParameter[1];

            parameters[0] = dbContext.CreateParameters("@serviceCode", service.Code);

            dataSet = dbContext.Read("GetServicePermissions", parameters);



            if (dataSet.Tables[0].Rows.Count > 0)
            {
                foreach (DataRow dr in dataSet.Tables[0].Rows)
                {
                    if (Helper.GetBoolDB(dr["IsGroup"]))
                    {
                        permissions.Add(new PermissionsGroupBE()
                        {
                            Id   = Helper.GetGuidDB(dr["PermissionID"]),
                            Name = Helper.GetStringDB(dr["Name"])
                        });
                    }
                    else
                    {
                        permissions.Add(new PermissionBE()
                        {
                            Id   = Helper.GetGuidDB(dr["PermissionID"]),
                            Name = Helper.GetStringDB(dr["Name"])
                        });
                    }
                }
            }


            return(permissions);
        }
 internal Yield PostServices(DreamContext context, DreamMessage request, Result <DreamMessage> response)
 {
     ServiceBL.EnsureServiceAdministrationAllowed();
     if (request.HasDocument && !request.ToDocument().IsEmpty)
     {
         //Add or Modify a service
         ServiceBE service = ServiceBL.PostServiceFromXml(request.ToDocument(), null);
         response.Return(DreamMessage.Ok(ServiceBL.GetServiceXmlVerbose(DekiContext.Current.Instance, service, null)));
     }
     else
     {
         //Backward compatibility: posting an empty document restarts all local services
         XDoc ret = new XDoc("services");
         foreach (ServiceBE service in ServiceBL.RestartServices())
         {
             ret.Add(ServiceBL.GetServiceXml(service, null));
         }
         response.Return(DreamMessage.Ok(ret));
     }
     yield break;
 }
Example #22
0
        public ServiceRepository.IServiceInfo CreateLocalService(ServiceBE service, string servicePath, XDoc config)
        {
            var      deki     = DekiContext.Current.Deki;
            Plug     location = deki.InternalCreateService(servicePath, service.SID, config, new Result <Plug>()).Wait();
            XUri     sid      = XUri.TryParse(service.SID);
            string   license;
            DateTime?expiration;

            if (deki.TryGetServiceLicense(sid, out license, out expiration) && (expiration != null))
            {
                lock (_serviceExpirations) {
                    TaskTimer timer;
                    if (_serviceExpirations.TryGetValue(service.Id, out timer))
                    {
                        timer.Cancel();
                    }
                    _serviceExpirations[service.Id] = TimerFactory.New(expiration.Value, _ => ServiceBL.StopService(service), null, TaskEnv.Clone());
                }
            }
            return(RunningServices.RegisterService(service, location.Uri, true));
        }
Example #23
0
        private static UserBE[] ProcessGroupMemberInput(GroupBE group, XDoc userList)
        {
            if (!userList.HasName("users"))
            {
                throw new GroupExpectedUserRootNodeInvalidArgumentException();
            }

            ServiceBE service = ServiceBL.GetServiceById(group.ServiceId);

            if (service == null)
            {
                throw new GroupServiceNotFoundFatalException(group.ServiceId, group.Name);
            }

            //Changing members of an external group is not supported. You may modify members in the external provider instead.
            if (!ServiceBL.IsLocalAuthService(service))
            {
                throw new ExternalGroupMemberInvalidOperationException();
            }

            UserBE[] members = ReadUserListXml(userList);
            ValidateGroupMemberList(service, members);
            return(members);
        }
Example #24
0
        //--- Class Methods ---
        public static UserBE Authenticate(DreamContext context, DreamMessage request, uint serviceId, bool autoCreateExternalUser, bool allowAnon, out bool altPassword)
        {
            UserBE user = null;

            altPassword = false;

            // Case 1: username/fullname, password, provider (login window)
            //      1. Validate & retrieve fullname using credentials
            //          Failed -> return null
            //      2. Populate user object
            //          A. Populates user info
            //          B. Populates group info in user object
            //      3. Does fullname exist?
            //          Yes -> Update user (email, fullname, ...)
            //          No  -> Create user
            //      4. Update Group information
            //      5. return user object
            //
            // Case 2: fullname, password (http, api, ...)
            //      1. Lookup full name, exist?
            //          Yes -> return user
            //          No -> return null
            //
            // Case 3: auth-token (header auth)
            //      0. Valid auth token?
            //          No -> return null
            //      1. Lookup user by name
            //          Found -> return user
            //          Else  -> return null

            string    userName      = null;
            string    password      = null;
            UserBE    userFromToken = null;
            ServiceBE authService   = null;

            // Extract authtoken and impersonation authtoken from request.
            // AllowAnon is false when in GET/POST: users/authenticate or when ?authenticate=true.
            // Standard user authtokens are ignored when AllowAnon=false but impersonation tokens are accepted.
            bool impersonationOnly = !allowAnon;

            userFromToken = UserFromAuthTokenInRequest(context, impersonationOnly);

            if (userFromToken == null)
            {
                HttpUtil.GetAuthentication(context.Uri.ToUri(), request.Headers, out userName, out password);
            }

            // check if we need to retrieve authentication service information
            if (serviceId > 0)
            {
                authService = ServiceBL.GetServiceById(serviceId);
                if (authService == null)
                {
                    throw new AuthServiceIdInvalidArgumentException(serviceId);
                }
                if (authService.Type != ServiceType.AUTH)
                {
                    throw new AuthNotAnAuthServiceInvalidArgumentException(serviceId);
                }
            }

            // check if a username was provided
            if (!string.IsNullOrEmpty(userName))
            {
                //Case 2: Given username + password
                if (authService == null)
                {
                    //Assuming local user or existing external account
                    user = DbUtils.CurrentSession.Users_GetByName(userName);
                    if (user != null)
                    {
                        serviceId   = user.ServiceId;
                        authService = ServiceBL.GetServiceById(serviceId);
                    }
                    else
                    {
                        LoginAccessDenied(context, request, userName, null, password);
                    }
                }
                if (authService == null)
                {
                    throw new AuthServiceIdInvalidArgumentException(serviceId);
                }
                if (authService.Type != ServiceType.AUTH)
                {
                    throw new AuthNotAnAuthServiceInvalidArgumentException(serviceId);
                }
                if (user == null)
                {
                    //Performing auth on local account
                    if (ServiceBL.IsLocalAuthService(authService))
                    {
                        user = DbUtils.CurrentSession.Users_GetByName(userName);
                    }
                    else
                    {
                        //Performing external auth. Lookup by external user name
                        user = DbUtils.CurrentSession.Users_GetByExternalName(userName, authService.Id);
                    }
                    if (user != null && user.ServiceId != authService.Id)
                    {
                        ServiceBE currentUsersAuthService = ServiceBL.GetServiceById(user.ServiceId);
                        if (currentUsersAuthService != null)
                        {
                            throw new AuthLoginExternalUserConflictException(currentUsersAuthService.Description);
                        }
                        throw new LoginExternalUserUnknownConflictException();
                    }
                }

                //Local account in the db.
                if (user != null && ServiceBL.IsLocalAuthService(authService))
                {
                    //Validate password for local account or validate the apikey
                    if (!IsValidAuthenticationForLocalUser(user, password, out altPassword))
                    {
                        // try impersonation using the ApiKey
                        if (string.IsNullOrEmpty(password) && PermissionsBL.ValidateRequestApiKey())
                        {
                            DekiContext.Current.Instance.Log.InfoFormat("user '{0}' authenticated via apikey impersonation", userName);
                        }
                        else
                        {
                            LoginAccessDenied(context, request, userName, user.ID, password);
                        }
                    }
                }

                // User was not found in the db and not being asked to create it.
                if (user == null && !autoCreateExternalUser)
                {
                    LoginAccessDenied(context, request, userName, null, password);
                }

                // Creating local account if apikey checks out and our authservice is local
                if (user == null && string.IsNullOrEmpty(password) && PermissionsBL.ValidateRequestApiKey() && ServiceBL.IsLocalAuthService(authService))
                {
                    XDoc newUserDoc = new XDoc("user")
                                      .Elem("username", userName);
                    DreamMessage newUserResponse = DekiContext.Current.ApiPlug.At("users")
                                                   .With("apikey", DreamContext.Current.GetParam("apikey", string.Empty))
                                                   .Post(newUserDoc);
                    user = UserBL.GetUserById(newUserResponse.ToDocument()["/user/@id"].AsUInt ?? 0);
                    if (user != null && !string.IsNullOrEmpty(password))
                    {
                        user = UserBL.SetPassword(user, password, false);
                    }
                }

                // Got an external account
                // Passing in the user object from db if it was found.
                List <GroupBE> externalGroups = null;
                if (!ServiceBL.IsLocalAuthService(authService))
                {
                    bool   bypassAuthentication = false;
                    string externalName;
                    if (user == null || string.IsNullOrEmpty(user.ExternalName))
                    {
                        externalName = userName;
                    }
                    else
                    {
                        externalName = user.ExternalName;
                    }

                    // If apikey is valid, try to bypass auth with the external provider
                    // and only lookup user/group details.
                    if (string.IsNullOrEmpty(password) && PermissionsBL.ValidateRequestApiKey())
                    {
                        DekiContext.Current.Instance.Log.InfoFormat("user '{0}' authenticating being bypassed via apikey impersonation", userName);
                        bypassAuthentication = true;
                    }

                    user = ExternalServiceSA.BuildUserFromAuthService(authService, user, userName, bypassAuthentication, externalName, password, out externalGroups);
                }

                // User was not found or did not authenticate with external provider
                if (user == null)
                {
                    LoginAccessDenied(context, request, userName, null, password);
                }
                else
                {
                    //New user creation from external provider
                    if (user.ID == 0)
                    {
                        if (!autoCreateExternalUser)
                        {
                            LoginAccessDenied(context, request, userName, null, password);
                        }
                    }
                    else
                    {
                        //user exists
                        // TODO (steveb): ???
                    }
                    if (user.UserActive)
                    {
                        user = UserBL.CreateOrUpdateUser(user);
                        if (externalGroups != null)
                        {
                            UserBL.UpdateUsersGroups(user, externalGroups.ToArray());
                        }
                    }
                }
            }
            else if (userFromToken != null)
            {
                // valid token exists that resolved to a user
                user = userFromToken;
            }
            else if (allowAnon)
            {
                // Anonymous user
                user = DbUtils.CurrentSession.Users_GetByName(DekiWikiService.ANON_USERNAME);
            }
            if (user == null)
            {
                //No credentials. Or token not provided or is invalid.
                LoginAccessDenied(context, request, null, null, password);
            }
            else if (!user.UserActive && !PermissionsBL.ValidateRequestApiKey())
            {
                //If a valid api key is provided, override the disabled account flag
                throw new AuthUserDisabledForbiddenException(user.Name);
            }
            return(user);
        }
Example #25
0
 public static ServiceBE StopService(ServiceBE service)
 {
     return(StopService(service.Id, service, ServiceStopType.Disable));
 }
Example #26
0
 //--- Methods ---
 public ServiceRepository.IServiceInfo RegisterRemoteService(ServiceBE service, XUri serviceUri)
 {
     return(RunningServices.RegisterService(service, serviceUri, false));
 }
Example #27
0
 public static XDoc GetServiceXmlVerbose(DekiInstance instance, ServiceBE service, string relation)
 {
     return(GetServiceXmlVerbose(DekiContext.Current.Instance, service, relation, true));
 }
Example #28
0
        //--- Class Methods ---
        public static void StartExtensionService(DekiContext context, ServiceBE service, ServiceRepository.IServiceInfo serviceInfo, bool forceRefresh)
        {
            // retrieve document describing the extension functions
            XUri            uri       = new XUri(service.Uri);
            XDoc            manifest  = null;
            DekiWikiService deki      = context.Deki;
            var             extension = serviceInfo.Extension;

            if (!service.ServiceLocal)
            {
                lock (deki.RemoteExtensionLibraries) {
                    deki.RemoteExtensionLibraries.TryGetValue(uri, out manifest);
                }
            }
            if (manifest == null || forceRefresh)
            {
                manifest = Plug.New(uri).Get().ToDocument();

                // normalize the extension XML
                manifest = manifest.TransformAsXml(_extensionConverterXslt);

                // check if document describes a valid extension: either the extension has no functions, or the functions have end-points
                if (manifest.HasName("extension") && ((manifest["function"].ListLength == 0) || (manifest["function/uri"].ListLength > 0)))
                {
                    // add source uri for service
                    manifest.Attr("uri", uri);

                    // register service in extension list
                    lock (deki.RemoteExtensionLibraries) {
                        deki.RemoteExtensionLibraries[uri] = manifest;
                    }
                }
                else
                {
                    throw new ExtensionRemoveServiceInvalidOperationException(uri);
                }
            }
            extension.Manifest = manifest;

            // add function prefix if one is defined
            serviceInfo.Extension.SetPreference("namespace.custom", service.Preferences["namespace"]);
            string serviceNamespace = service.Preferences["namespace"] ?? manifest["namespace"].AsText;

            if (serviceNamespace != null)
            {
                serviceNamespace = serviceNamespace.Trim();
                if (string.IsNullOrEmpty(serviceInfo.Namespace))
                {
                    // Note (arnec): Namespace from preferences is assigned at service creation. If we do not have one at this
                    // point, it came from the extension manifest and needs to be registered as our default. Otherwise the
                    // preference override persists as the namespace.
                    context.Instance.RunningServices.RegisterNamespace(serviceInfo, serviceNamespace);
                }
                if (serviceNamespace.Length != 0)
                {
                    if (!DekiScriptParser.IsIdentifier(serviceNamespace))
                    {
                        throw new ExtensionNamespaceInvalidArgumentException(service.Preferences["namespace"] ?? manifest["namespace"].AsText);
                    }
                }
                else
                {
                    serviceNamespace = null;
                }
            }
            serviceNamespace = (serviceNamespace == null) ? string.Empty : (serviceNamespace + ".");

            // add custom library title

            extension.SetPreference("title.custom", service.Preferences["title"]);
            extension.SetPreference("label.custom", service.Preferences["label"]);
            extension.SetPreference("description.custom", service.Preferences["description"]);
            extension.SetPreference("uri.logo.custom", service.Preferences["uri.logo"]);
            extension.SetPreference("functions", service.Preferences["functions"]);
            extension.SetPreference("protected", service.Preferences["protected"]);

            // add each extension function
            bool.TryParse(service.Preferences["protected"], out extension.IsProtected);
            var functions = new List <ServiceRepository.ExtensionFunctionInfo>();

            foreach (XDoc function in manifest["function"])
            {
                XUri functionUri = function["uri"].AsUri;
                if (functionUri != null)
                {
                    functions.Add(new ServiceRepository.ExtensionFunctionInfo(serviceNamespace + function["name"].Contents, functionUri));
                }
            }
            extension.Functions = functions.ToArray();
        }
Example #29
0
        //--- Class Methods ---
        public static ServiceBE StartService(ServiceBE service, bool forceRefresh, bool disableOnFailure)
        {
            // create subordinate request id for service start
            var dreamContext = DreamContext.Current;
            var requestId    = dreamContext.GetState <string>(DreamHeaders.DREAM_REQUEST_ID);

            dreamContext.SetState(DreamHeaders.DREAM_REQUEST_ID, requestId + "-service_" + service.Id);

            try {
                var stopwatch = Stopwatch.StartNew();
                service.ServiceLastStatus = string.Empty;
                StopService(service.Id, service, ServiceStopType.Restart);
                DekiContext context            = DekiContext.Current;
                bool        dirtyServiceEntity = false;
                XUri        location;
                ServiceRepository.IServiceInfo serviceInfo = null;
                try {
                    // check if service is local
                    if (service.ServiceLocal)
                    {
                        if (string.IsNullOrEmpty(service.SID))
                        {
                            throw new Exception("missing SID");
                        }

                        // start service
                        if (IsLocalAuthService(service))
                        {
                            // this service is the built-in authentication provider; no need to start it
                            location = context.Deki.Self;
                        }
                        else
                        {
                            // convert local service configuration into an xdoc
                            XDoc config = new XDoc("config");
                            foreach (KeyValuePair <string, string> configEntry in ArrayUtil.AllKeyValues(service.Config))
                            {
                                config.InsertValueAt(configEntry.Key, configEntry.Value);
                            }

                            // if no apikey was provided, create a random one so that CreateService doesn't inject the parent one
                            if (config["apikey"].IsEmpty)
                            {
                                config.Elem("apikey", StringUtil.CreateAlphaNumericKey(16));
                            }

                            // add information for service to callback into deki
                            if (config["uri.deki"].IsEmpty)
                            {
                                config.Elem("uri.deki", context.Deki.Self);
                                config.Elem("wikiid.deki", context.Instance.Id);

                                // Providing master apikey to service for setups that don't use per instance keys
                                config.Elem("apikey.deki", context.Instance.ApiKey.IfNullOrEmpty(context.Deki.MasterApiKey));
                            }

                            // the service location must use the service ID and the instance ID
                            string servicePath = string.Format("services/{0}/{1}", context.Instance.Id, service.Id);
                            _log.DebugFormat("starting service '{0}' at path {1} w/ namespace {2}", service.SID, servicePath, service.Preferences["namespace"]);
                            serviceInfo = context.Instance.CreateLocalService(service, servicePath, config);
                            location    = serviceInfo.ServiceUri;
                        }

                        // check if the service uri has changed since last invocation (happens when service is started for the first time or server GUID has changed)
                        if (!service.Uri.EqualsInvariantIgnoreCase(location.ToString()))
                        {
                            dirtyServiceEntity = true;
                            service.Uri        = location.ToString();
                        }
                    }
                    else
                    {
                        _log.DebugFormat("registering remote service '{0}'", service.SID);
                        if (string.IsNullOrEmpty(service.Uri))
                        {
                            throw new Exception("missing URI");
                        }
                        location    = new XUri(service.Uri);
                        serviceInfo = context.Instance.RegisterRemoteService(service, location);
                    }

                    // check if service is an Extension service
                    if (service.Type == ServiceType.EXT)
                    {
                        if (service.ServiceLocal)
                        {
                            _log.DebugFormat("registering service '{0}' as extension", service.SID);
                        }
                        ExtensionBL.StartExtensionService(context, service, serviceInfo, forceRefresh);
                    }

                    //Successfully starting a service enables it.
                    if (!service.ServiceEnabled)
                    {
                        dirtyServiceEntity     = true;
                        service.ServiceEnabled = true;
                    }
                } catch (Exception e) {
                    dirtyServiceEntity = true;
                    DreamMessage dm = null;
                    if (e is DreamResponseException)
                    {
                        dm = ((DreamResponseException)e).Response;
                        string message = dm.HasDocument ? dm.ToDocument()[".//message"].AsText.IfNullOrEmpty(e.Message) : dm.ToText();
                        service.ServiceLastStatus = string.Format("unable to initialize service ({0})", message);
                    }
                    else
                    {
                        service.ServiceLastStatus = e.GetCoroutineStackTrace();
                    }
                    if (serviceInfo != null)
                    {
                        try {
                            context.Instance.DeregisterService(service.Id);
                        } catch { }
                    }

                    // A service that fails to start becomes disabled if it's started explicitly (not during deki startup)
                    if (disableOnFailure)
                    {
                        service.ServiceEnabled = false;
                    }
                    _log.ErrorExceptionMethodCall(e, "StartService", string.Format("Unable to start local service id '{0}' with SID '{1}' Error: '{2}'", service.Id, service.SID, service.ServiceLastStatus));
                    if (dm != null)
                    {
                        throw new ExternalServiceResponseException(dm);
                    }
                    else
                    {
                        throw;
                    }
                } finally {
                    // don't update remote services that haven't changed
                    if (dirtyServiceEntity)
                    {
                        service = UpdateService(service);
                    }
                }
                stopwatch.Stop();
                _log.InfoFormat("Service '{0}' ({1}) started in {2}ms", service.Description, service.SID, stopwatch.ElapsedMilliseconds);
                return(service);
            } finally {
                // restore the request id
                dreamContext.SetState(DreamHeaders.DREAM_REQUEST_ID, requestId);
            }
        }
Example #30
0
        public uint Services_Insert(ServiceBE service)
        {
            StringBuilder query = null;

            if (service.Id == 0)
            {
                //new service
                query = new StringBuilder(@" /* Services_Insert */
insert into services (service_type, service_sid, service_uri, service_description, service_local, service_enabled, service_last_edit, service_last_status)
values (?TYPE, ?SID, ?URI, ?DESC, ?LOCAL, ?ENABLED, ?TIMESTAMP, ?LASTSTATUS);
");
                query.AppendLine("select LAST_INSERT_ID() into @service_id;");
                query.AppendLine("select LAST_INSERT_ID() as service_id;");
            }
            else
            {
                //update existing service
                query = new StringBuilder(@" /* Services_Insert (with id) */
insert into services (service_id, service_type, service_sid, service_uri, service_description, service_local, service_enabled, service_last_edit, service_last_status)
values (?ID, ?TYPE, ?SID, ?URI, ?DESC, ?LOCAL, ?ENABLED, ?TIMESTAMP, ?LASTSTATUS);
");
                query.AppendLine(string.Format("select {0} into @service_id;", service.Id));
                query.AppendLine(string.Format("select {0} as service_id;", service.Id));
            }

            if (service.Preferences != null && service.Preferences.Count > 0)
            {
                query.Append("insert into service_prefs (service_id, pref_name, pref_value) values ");
                for (int i = 0; i < service.Preferences.AllKeys.Length; i++)
                {
                    string key = DataCommand.MakeSqlSafe(service.Preferences.AllKeys[i]);
                    string val = DataCommand.MakeSqlSafe(service.Preferences[key]);
                    query.AppendFormat("{0}(@service_id, '{1}', '{2}')\n", i > 0 ? "," : string.Empty, key, val);
                }
                query.AppendLine(";");
            }

            if (service.Config != null && service.Config.Count > 0)
            {
                query.Append("insert into service_config (service_id, config_name, config_value) values ");
                for (int i = 0; i < service.Config.AllKeys.Length; i++)
                {
                    string key = DataCommand.MakeSqlSafe(service.Config.AllKeys[i]);
                    string val = DataCommand.MakeSqlSafe(service.Config[key]);
                    query.AppendFormat("{0}(@service_id, '{1}', '{2}')\n", i > 0 ? "," : string.Empty, key, val);
                }
                query.AppendLine(";");
            }
            uint serviceId = 0;

            try {
                serviceId = Catalog.NewQuery(query.ToString())
                            .With("ID", service.Id)
                            .With("TYPE", service.Type.ToString())
                            .With("SID", service.SID)
                            .With("URI", service.Uri)
                            .With("DESC", service.Description)
                            .With("LOCAL", service.ServiceLocal)
                            .With("ENABLED", service.ServiceEnabled)
                            .With("TIMESTAMP", service.ServiceLastEdit)
                            .With("LASTSTATUS", service.ServiceLastStatus)
                            .ReadAsUInt() ?? 0;
            } catch (MySqlException e) {
                // catch Duplicate Key (1062)
                if (e.Number == 1062)
                {
                    serviceId = service.Id;
                }
                else
                {
                    throw;
                }
            }
            return(serviceId);
        }