Example #1
0
        public DialogContextStandalone DialogSettings(int appId)
        {
            // reset app-id if we get a info-token like -100
            if (appId < 0)
            {
                appId = Eav.Constants.AppIdEmpty;
            }

            var appContext = appId != Eav.Constants.AppIdEmpty ? _ctxResolver.BlockOrApp(appId) : null;
            var context    = appContext ?? _ctxResolver.Site();

            // if we have an appid (we don't have it in an install-new-apps-scenario) check permissions
            if (appContext != null)
            {
                var appAndPerms = ServiceProvider.Build <MultiPermissionsApp>().Init(appContext, appContext.AppState, Log);
                if (!appAndPerms.ZoneIsOfCurrentContextOrUserIsSuper(out var error))
                {
                    throw HttpException.PermissionDenied(error);
                }
            }

            var cb = _uiContextBuilder.SetZoneAndApp(context.Site.ZoneId, appContext?.AppState);

            return(new DialogContextStandalone
            {
                Context = cb.Get(Ctx.All),
            });
        }
Example #2
0
        public IEnumerable <ViewDto> ViewUsage(int appId, Guid guid, Func <List <IView>, List <BlockConfiguration>, IEnumerable <ViewDto> > finalBuilder)
        {
            var wrapLog = Log.Call <IEnumerable <ViewDto> >($"{appId}, {guid}");
            var context = _ctxResolver.BlockOrApp(appId);

            // extra security to only allow zone change if host user
            var permCheck = ServiceProvider.Build <MultiPermissionsApp>().Init(context, context.AppState, Log);

            if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var error))
            {
                throw HttpException.PermissionDenied(error);
            }

            var cms = _cmsRuntime.Init(context.AppState, context.UserMayEdit, Log);
            // treat view as a list - in case future code will want to analyze many views together
            var views = new List <IView> {
                cms.Views.Get(guid)
            };

            var blocks = cms.Blocks.AllWithView();

            Log.Add($"Found {blocks.Count} content blocks");

            var result = finalBuilder(views, blocks);

            return(wrapLog("ok", result));
        }
Example #3
0
        public T Init(int appId, string contentType, Guid itemGuid, string field, bool usePortalRoot, ILog parentLog)

        {
            Log.LinkTo(parentLog);
            var context = appId > 0 ? _ctxResolver.BlockOrApp(appId) : _ctxResolver.AppNameRouteBlock(null);
            var logCall = Log.Call <T>($"app: {context.AppState.Show()}, type: {contentType}, itemGuid: {itemGuid}, field: {field}, portalRoot: {usePortalRoot}");

            AdamContext.Init(context, contentType, field, itemGuid, usePortalRoot, Log);
            return(logCall(null, this as T));
        }
Example #4
0
 public EditSaveBackend Init(int appId, ILog log)
 {
     Init(log);
     _appId = appId;
     // The context should be from the block if there is one, because it affects saving/publishing
     // Basically it can result in things being saved draft or titles being updated
     _context = _ctxResolver.BlockOrApp(appId);
     _pagePublishing.Init(_context, Log);
     return(this);
 }
Example #5
0
        public string ResolveHyperlink(int appId, string hyperlink, string contentType, Guid guid, string field)
        {
            try
            {
                var context = _ctxResolver.BlockOrApp(appId);
                // different security checks depending on the link-type
                var lookupPage = hyperlink.Trim().StartsWith("page", StringComparison.OrdinalIgnoreCase);

                // look it up first, because we need to know if the result is in ADAM or not (different security scenario)
                var conv     = ServiceProvider.Build <IValueConverter>();
                var resolved = conv.ToValue(hyperlink, guid);

                if (lookupPage)
                {
                    // page link - only resolve if the user has edit-permissions
                    // only people who have some full edit permissions may actually look up pages
                    var permCheckPage = ServiceProvider.Build <MultiPermissionsApp>().Init(context, context.AppState, Log);
                    return(permCheckPage.UserMayOnAll(GrantSets.WritePublished)
                                                ? resolved
                                                : hyperlink);
                }

                // for file, we need guid & field - otherwise return the original unmodified
                if (guid == default || string.IsNullOrEmpty(field) || string.IsNullOrEmpty(contentType))
                {
                    return(hyperlink);
                }

                var isOutsideOfAdam = !(resolved.IndexOf($"/{AdamConstants.AdamRootFolder}/", StringComparison.Ordinal) > 0);

                // file-check, more abilities to allow
                // this will already do a ensure-or-throw inside it if outside of adam
                var adamCheck = AdamContext; // new AdamState<int, int>();
                adamCheck.Init(context, contentType, field, guid, isOutsideOfAdam, Log);
                if (!adamCheck.Security.SuperUserOrAccessingItemFolder(resolved, out var exp))
                {
                    throw exp;
                }
                if (!adamCheck.Security.UserIsPermittedOnField(GrantSets.ReadSomething, out exp))
                {
                    throw exp;
                }

                // if everything worked till now, it's ok to return the result
                return(resolved);
            }
            catch
            {
                return(hyperlink);
            }
        }
Example #6
0
        public Dictionary <string, IEnumerable <Dictionary <string, object> > > Query(int?appId, string name, bool includeGuid, string stream)
        {
            var wrapLog = Log.Call($"'{name}', inclGuid: {includeGuid}, stream: {stream}");

            var appCtx = appId != null?_ctxResolver.BlockOrApp(appId.Value) : _ctxResolver.BlockRequired();

            // If no app available from context, check if an app-id was supplied in url
            // Note that it may only be an app from the current portal
            // and security checks will run internally
            var app = ServiceProvider.Build <Apps.App>().Init(ServiceProvider, appCtx.AppState.AppId, Log, appCtx.UserMayEdit);

            var result = BuildQueryAndRun(app, name, stream, includeGuid, appCtx, Log, appCtx.UserMayEdit);

            wrapLog(null);
            return(result);
        }
Example #7
0
        // New feature in 11.03 - Usage Statistics

        public dynamic Usage(int appId, Guid guid)
        {
            var context   = _ctxResolver.BlockOrApp(appId);
            var permCheck = ServiceProvider.Build <MultiPermissionsApp>().Init(context, context.AppState, Log);

            if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var error))
            {
                throw HttpException.PermissionDenied(error);
            }

            var item          = context.AppState.List.One(guid);
            var relationships = item.Relationships.AllRelationships;

            // var result = relationships.Select(r => new EntityInRelationDto(r.))
            // todo: don't forget Metadata relationships
            return(null);
        }
Example #8
0
        public IEnumerable <EntityForPickerDto> GetAvailableEntities(int appId, string[] items, string contentTypeName)
        {
            var context = _ctxResolver.BlockOrApp(appId);
            // do security check
            var permCheck = string.IsNullOrEmpty(contentTypeName)
                ? ServiceProvider.Build <MultiPermissionsApp>().Init(context, context.AppState, Log)
                : ServiceProvider.Build <MultiPermissionsTypes>().Init(context, context.AppState, contentTypeName, Log);

            if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var error))
            {
                throw HttpException.PermissionDenied(error);
            }

            // maybe in the future, ATM not relevant
            var withDrafts = permCheck.EnsureAny(GrantSets.ReadDraft);

            return(_entityPickerApi.Init(Log).GetAvailableEntities(appId, items, contentTypeName, withDrafts));
        }
Example #9
0
        // 2021-04-13 2dm should be unused now
        //public string ResolveHyperlink(int appId, string hyperlink, string contentType, Guid guid, string field)
        //{
        //	try
        //	{
        //		var context = _ctxResolver.BlockOrApp(appId);
        //		// different security checks depending on the link-type
        //		var lookupPage = hyperlink.Trim().StartsWith(ValueConverterBase.PrefixPage, StringComparison.OrdinalIgnoreCase);

        //		// look it up first, because we need to know if the result is in ADAM or not (different security scenario)
        //		var conv = ServiceProvider.Build<IValueConverter>();
        //		var resolved = conv.ToValue(hyperlink, guid);

        //		if (lookupPage)
        //		{
        //			// page link - only resolve if the user has edit-permissions
        //			// only people who have some full edit permissions may actually look up pages
        //			var permCheckPage = ServiceProvider.Build<MultiPermissionsApp>().Init(context, context.AppState, Log);
        //			return permCheckPage.UserMayOnAll(GrantSets.WritePublished)
        //				? resolved
        //				: hyperlink;
        //		}

        //		// for file, we need guid & field - otherwise return the original unmodified
        //		if (guid == default || string.IsNullOrEmpty(field) || string.IsNullOrEmpty(contentType))
        //			return hyperlink;

        //		var isOutsideOfAdam = !(resolved.IndexOf($"/{AdamConstants.AdamRootFolder}/", StringComparison.Ordinal) > 0);

        //		// file-check, more abilities to allow
        //		// this will already do a ensure-or-throw inside it if outside of adam
        //              var adamCheck = AdamContext; // new AdamState<int, int>();
        //              adamCheck.Init(context, contentType, field, guid, isOutsideOfAdam, Log);
        //		if (!adamCheck.Security.SuperUserOrAccessingItemFolder(resolved, out var exp))
        //			throw exp;
        //		if (!adamCheck.Security.UserIsPermittedOnField(GrantSets.ReadSomething, out exp))
        //			throw exp;

        //		// if everything worked till now, it's ok to return the result
        //		return resolved;
        //	}
        //	catch
        //	{
        //		return hyperlink;
        //	}
        //}

        public LinkInfoDto LookupHyperlink(int appId, string hyperlink, string contentType, Guid guid, string field)
        {
            try
            {
                var context = _ctxResolver.BlockOrApp(appId);
                // different security checks depending on the link-type
                var lookupPage = hyperlink.Trim().StartsWith(ValueConverterBase.PrefixPage, StringComparison.OrdinalIgnoreCase);

                // look it up first, because we need to know if the result is in ADAM or not (different security scenario)
                var conv     = ServiceProvider.Build <IValueConverter>();
                var resolved = conv.ToValue(hyperlink, guid);

                if (lookupPage)
                {
                    // page link - only resolve if the user has edit-permissions
                    // only people who have some full edit permissions may actually look up pages
                    var permCheckPage = ServiceProvider.Build <MultiPermissionsApp>().Init(context, context.AppState, Log);
                    var userMay       = permCheckPage.UserMayOnAll(GrantSets.WritePublished);
                    return(new LinkInfoDto {
                        Value = userMay ? resolved : hyperlink
                    });
                }

                // for file, we need guid & field - otherwise return the original unmodified
                if (guid == default || string.IsNullOrEmpty(field) || string.IsNullOrEmpty(contentType))
                {
                    return new LinkInfoDto {
                               Value = hyperlink
                    }
                }
                ;

                var isOutsideOfAdam = !Sxc.Adam.Security.PathIsInItemAdam(guid, field, resolved);

                // file-check, more abilities to allow
                // this will already do a ensure-or-throw inside it if outside of adam
                var adamContext = AdamContext;
                adamContext.Init(context, contentType, field, guid, isOutsideOfAdam, Log);
                if (!adamContext.Security.SuperUserOrAccessingItemFolder(resolved, out var exp))
                {
                    throw exp;
                }
                if (!adamContext.Security.UserIsPermittedOnField(GrantSets.ReadSomething, out exp))
                {
                    throw exp;
                }

                // now try to find the item
                // we already know that the link was able to match, so we'll just use this to get the id
                var parts = new ValueConverterBase.LinkParts(hyperlink);
                // Note: kind of temporary solution, will fail if TFileId isn't int!
                var file     = ((IAdamFileSystem <int, int>)adamContext.AdamManager.AdamFs).GetFile(parts.Id);
                var dtoMaker = AdamContext.ServiceProvider.Build <AdamItemDtoMaker <TFolderId, TFileId> >().Init(AdamContext);
                // if everything worked till now, it's ok to return the result
                var adam = dtoMaker.Create(file as File <TFolderId, TFileId>);
                return(new LinkInfoDto {
                    Adam = adam, Value = adam.Url
                });
            }
            catch
            {
                return(new LinkInfoDto {
                    Value = hyperlink
                });
            }
        }
Example #10
0
        public EditDto Load(int appId, List <ItemIdentifier> items)
        {
            // Security check
            var wrapLog = Log.Call($"load many a#{appId}, items⋮{items.Count}");

            var context = _ctxResolver.BlockOrApp(appId);

            var showDrafts = context.UserMayEdit;

            // do early permission check - but at this time it may be that we don't have the types yet
            // because they may be group/id combinations, without type information which we'll look up afterwards
            var appIdentity = State.Identity(null, appId);

            items = _contentGroupList.Init(appIdentity, Log, showDrafts).ConvertListIndexToId(items);
            TryToAutoFindMetadataSingleton(items, context.AppState);

            // now look up the types, and repeat security check with type-names
            // todo: 2020-03-20 new feat 11.01, may not check inner type permissions ATM
            var permCheck = ServiceProvider.Build <MultiPermissionsTypes>().Init(context, context.AppState, items, Log);

            if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var error))
            {
                throw HttpException.PermissionDenied(error);
            }

            // load items - similar
            var result         = new EditDto();
            var entityApi      = _entityApi.Init(appId, permCheck.EnsureAny(GrantSets.ReadDraft), Log);
            var typeRead       = entityApi.AppRead.ContentTypes;
            var list           = entityApi.GetEntitiesForEditing(items);
            var jsonSerializer = ServiceProvider.Build <JsonSerializer>();

            result.Items = list.Select(e => new BundleWithHeader <JsonEntity>
            {
                Header = e.Header,
                Entity = GetSerializeAndMdAssignJsonEntity(appId, e, jsonSerializer, typeRead)
            }).ToList();

            // set published if some data already exists
            if (list.Any())
            {
                result.IsPublished = list.First().Entity?.IsPublished ?? true; // Entity could be null (new), then true
                // only set draft-should-branch if this draft already has a published item
                if (!result.IsPublished)
                {
                    result.DraftShouldBranch = list.First().Entity?.GetPublished() != null;
                }
            }

            // since we're retrieving data - make sure we're allowed to
            // this is to ensure that if public forms only have create permissions, they can't access existing data
            // important, this code is shared/duplicated in the EntitiesController.GetManyForEditing
            if (list.Any(set => set.Entity != null))
            {
                if (!permCheck.EnsureAll(GrantSets.ReadSomething, out error))
                {
                    throw HttpException.PermissionDenied(error);
                }
            }

            // load content-types
            var types = UsedTypes(list, typeRead);

            result.ContentTypes = types
                                  .Select(ct => JsonSerializer.ToJson(ct, true))
                                  .ToList();

            //// TEMP DEBUG
            //var inputTypes = types.SelectMany(t => t.Attributes.Select(a =>
            //{
            //    var Lookup = a.InputType();
            //    var mdAll = a.Metadata.Where(md => md.Type.Is(Constants.MetadataFieldTypeAll)).ToList();
            //    var MdAllCount = mdAll.Count;
            //    var MdAllAttribCount = mdAll.FirstOrDefault()?.Attributes.Count;
            //    var MdAllWithAttrib = mdAll.FirstOrDefault(md => md.Attributes.ContainsKey(Constants.MetadataFieldTypeAll));
            //    var MdAllAttrib = MdAllWithAttrib?.GetBestValue<string>(Constants.MetadataFieldTypeAll);
            //    var MdAllAttribZero = MdAllWithAttrib?.GetBestValue<string>(Constants.MetadataFieldTypeAll, new string[0]);
            //    var MdAllAttribEmpty = MdAllWithAttrib?.GetBestValue<string>(Constants.MetadataFieldTypeAll, new []{""});
            //    var MdAllAttribEn = MdAllWithAttrib?.GetBestValue<string>(Constants.MetadataFieldTypeAll, new[] { "en-us" });
            //    var MdAllAttribTr = MdAllWithAttrib?.GetBestValue<string>(Constants.MetadataFieldTypeAll, new[] { "tr-tr" });
            //    var MdAllType = a.Metadata.GetBestValue<string>(Constants.MetadataFieldAllInputType, Constants.MetadataFieldTypeAll);
            //    return new {Lookup, MdAllCount, MdAllType, MdAllAttribCount, MdAllWithAttrib?.EntityId, MdAllAttrib, MdAllAttribZero, MdAllAttribEmpty, MdAllAttribEn, MdAllAttribTr };
            //}));
            //var serializedDebug = JsonConvert.SerializeObject(inputTypes);
            //Log.Add("Test / debug: " + serializedDebug);

            // ensure that sub-properties of the content-types are included
            // this is for UI Formulas (children of @All) - WIP
            // and the warning/error Regex specials - WIP
            var entList = types.SelectMany(
                // in all Content-Type attributes like title, body etc.
                t => t.Attributes.SelectMany(
                    // check all metadata of these attributes - get possible sub-entities attached
                    a => a.Metadata.SelectMany(m => m.Children())
                    )
                );

            result.ContentTypeItems = entList.Select(e => jsonSerializer.ToJson(e, 0, Log)).ToList();

            // Fix not-supported input-type names; map to correct name
            result.ContentTypes
            .ForEach(jt => jt.Attributes
                     .ForEach(at => at.InputType = InputTypes.MapInputTypeV10(at.InputType)));

            // load input-field configurations
            result.InputTypes = GetNecessaryInputTypes(result.ContentTypes, typeRead);

            // also include UI features
            result.Features = FeaturesHelpers.FeatureListWithPermissionCheck(permCheck).ToList();

            // Attach context, but only the minimum needed for the UI
            result.Context = _contextBuilder.SetZoneAndApp(appIdentity.ZoneId, context.AppState)
                             .Get(Ctx.AppBasic | Ctx.Language | Ctx.Site | Ctx.System);

            try
            {
                result.Prefetch = TryToPrefectAdditionalData(appId, result);
            }
            catch (Exception) { /* ignore */ }

            // done - return
            wrapLog($"ready, sending items:{result.Items.Count}, " +
                    $"types:{result.ContentTypes.Count}, " +
                    $"inputs:{result.InputTypes.Count}, " +
                    $"feats:{result.Features.Count}");
            return(result);
        }