[AllowAnonymous]   // will check security internally, so assume no requirements
        public IEnumerable <Dictionary <string, object> > GetEntities(string contentType, string appPath = null, string cultureCode = null)
        {
            var wraplog = Log.Call($"get entities type:{contentType}, path:{appPath}, culture:{cultureCode}");

            // if app-path specified, use that app, otherwise use from context
            var appIdentity = AppFinder.GetAppIdFromPathOrContext(appPath, BlockBuilder);

            // verify that read-access to these content-types is permitted
            var permCheck = new MultiPermissionsTypes(BlockBuilder, appIdentity.AppId, contentType, Log);

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

            //2018-09-15 2dm replaced
            //var context = GetContext(SxcBlock, Log);
            //PerformSecurityCheck(appIdentity, contentType, Grants.Read, appPath == null ? context.Dnn.Module : null);
            var result = new EntityApi(appIdentity.AppId, permCheck.EnsureAny(GrantSets.ReadDraft), Log)
                         .GetEntities(contentType, cultureCode)
                         ?.ToList();

            wraplog("found: " + result?.Count);
            return(result);
        }
Beispiel #2
0
        internal IEnumerable <Dictionary <string, object> > GetItems(IInstanceContext context, string contentType, IBlock ctxBlock, string appPath = null)
        {
            var wrapLog = Log.Call($"get entities type:{contentType}, path:{appPath}");

            // if app-path specified, use that app, otherwise use from context
            var appIdentity = AppFinder.GetAppIdFromPathOrContext(appPath, ctxBlock);

            // get the app - if we have the context from the request, use that, otherwise generate full app
            var app = ctxBlock == null
                ? Factory.Resolve <Apps.App>().Init(appIdentity, Log)
                : GetApp(appIdentity.AppId, ctxBlock);

            // verify that read-access to these content-types is permitted
            var permCheck = new MultiPermissionsTypes().Init(context, app, contentType, Log);

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

            var result = new EntityApi(appIdentity.AppId, permCheck.EnsureAny(GrantSets.ReadDraft), Log)
                         .GetEntities(contentType)
                         ?.ToList();

            wrapLog("found: " + result?.Count);
            return(result);
        }
Beispiel #3
0
        public IEnumerable <Dictionary <string, object> > GetAllOfTypeForAdmin(int appId, string contentType)
        {
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log);

            if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exception))
            {
                throw exception;
            }
            return(new EntityApi(appId, Log).GetEntitiesForAdmin(contentType));
        }
Beispiel #4
0
        public Dictionary <string, object> GetOne(string contentType, int id, int appId, string cultureCode = null)
        {
            var permCheck = new MultiPermissionsTypes(BlockBuilder, appId, contentType, Log);

            if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exception))
            {
                throw exception;
            }
            return(new EntityApi(appId, true, Log).GetOne(contentType, id, cultureCode));  // note that the culture-code isn't actually used...
        }
Beispiel #5
0
        public void Delete(string contentType, Guid guid, int appId, bool force = false)
        {
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log);

            if (!permCheck.EnsureAll(GrantSets.DeleteSomething, out var exception))
            {
                throw exception;
            }
            new EntityApi(appId, Log).Delete(contentType, guid, force);
        }
Beispiel #6
0
        public AllInOne Load([FromBody] List <ItemIdentifier> items, int appId)
        {
            // Security check
            var wraplog = Log.Call("Load", $"load many a#{appId}, items⋮{items.Count}");

            // 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 appForSecurityChecks = App.LightWithoutData(new DnnTenant(PortalSettings), appId, Log);

            items = new SaveHelpers.ContentGroupList(SxcInstance, Log).ConvertListIndexToId(items, appForSecurityChecks);

            // now look up the types, and repeat security check with type-names
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, items, Log);

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

            // load items - similar
            var result         = new AllInOne();
            var entityApi      = new EntityApi(appId, Log);
            var typeRead       = entityApi.AppManager.Read.ContentTypes;
            var list           = entityApi.GetEntitiesForEditing(appId, items);
            var jsonSerializer = new JsonSerializer();

            result.Items = list.Select(e => new BundleWithHeader <JsonEntity>
            {
                Header = e.Header,
                Entity = jsonSerializer.ToJson(e.Entity ?? ConstructEmptyEntity(appId, e.Header, 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
            }
            // load content-types
            var types = UsedTypes(list, typeRead);

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

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

            // also deliver features
            result.Features = SystemController.FeatureListWithPermissionCheck(appId, permCheck).ToList();

            // done - return
            wraplog($"ready, sending items:{result.Items.Count}, " +
                    $"types:{result.ContentTypes.Count}, " +
                    $"inputs:{result.InputTypes.Count}, " +
                    $"feats:{result.Features.Count}");
            return(result);
        }
Beispiel #7
0
        public Dictionary <string, object> GetOne(string contentType, int id, int appId, string cultureCode = null)
        {
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log);

            if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exception))
            {
                throw exception;
            }
            // 2018-09-15 old code, should have checked the same stuff mostly...
            //new AppPermissionBeforeUsing(SxcInstance, Log)
            //    .ConfirmPermissionsOrThrow(contentType, appId, Grants.Read);
            return(new EntityApi(appId, Log).GetOne(contentType, id, cultureCode));  // note that the culture-code isn't actually used...
        }
        public void Delete(string contentType, Guid guid, int appId, bool force = false)
        {
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log);

            if (!permCheck.EnsureAll(GrantSets.DeleteSomething, out var exception))
            {
                throw exception;
            }
            // 2018-09-15 old code, should have checked the same stuff mostly...
            //new AppPermissionBeforeUsing(SxcInstance, Log)
            //    .ConfirmPermissionsOrThrow(contentType, appId, GrantSets.DeleteSomething);
            new EntityApi(appId, Log).Delete(contentType, guid, force);
        }
        public IEnumerable <Dictionary <string, object> > GetAllOfTypeForAdmin(int appId, string contentType)
        {
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log);

            if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exception))
            {
                throw exception;
            }
            // 2018-09-15 old code, should have checked the same stuff mostly...
            //new AppPermissionBeforeUsing(SxcInstance, Log)
            //       .ConfirmPermissionsOrThrow(contentType, appId, Grants.Read);
            return(new EntityApi(appId, Log).GetEntitiesForAdmin(contentType));
        }
Beispiel #10
0
        public IEnumerable <ContentTypeFieldInfo> GetFields(int appId, string staticName)
        {
            Log.Add($"get fields for a:{appId} type:{staticName}");
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, staticName, Log);

            if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var exp))
            {
                throw exp;
            }
            if (!permCheck.UserCanWriteAndPublicFormsEnabled(out exp))
            {
                throw exp;
            }

            return(_eavCtc.GetFields(appId, staticName));
        }
Beispiel #11
0
        public dynamic GetSingle(int appId, string contentTypeStaticName, string scope = null)
        {
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentTypeStaticName, Log);

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

            if (!permCheck.UserCanWriteAndPublicFormsEnabled(out exp))
            {
                throw exp;
            }

            // if we got this far, permissions are ok
            return(_eavCtc.GetSingle(appId, contentTypeStaticName, scope));
        }
Beispiel #12
0
        public IMultiPermissionCheck DoPreSaveSecurityCheck(int appId, IEnumerable <BundleWithHeader> items)
        {
            var app       = Factory.Resolve <Apps.App>().Init(appId, Log, Block);
            var permCheck = new MultiPermissionsTypes().Init(Block.Context, app, items.Select(i => i.Header).ToList(), Log);

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

            Log.Add("passed security checks");
            return(permCheck);
        }
Beispiel #13
0
        /// <summary>
        /// Initializes the object and performs all the initial security checks
        /// </summary>
        public virtual AdamContext Init(IContextOfApp context, string contentType, string fieldName, Guid entityGuid, bool usePortalRoot, ILog parentLog)
        {
            Log.LinkTo(parentLog);
            var appId   = context.AppState.AppId;
            var callLog = Log.Call <AdamContext>($"app: {context.AppState.Show()}, field:{fieldName}, guid:{entityGuid}");

            Context = context;

            Permissions = ServiceProvider.Build <MultiPermissionsTypes>()
                          .Init(context, context.AppState, contentType, Log);

            // only do checks on field/guid if it's actually accessing that, if it's on the portal root, don't.
            UseSiteRoot = usePortalRoot;
            if (!usePortalRoot)
            {
                ItemField = fieldName;
                ItemGuid  = entityGuid;
            }

            Security = ServiceProvider.Build <AdamSecurityChecksBase>().Init(this, usePortalRoot, Log);

            if (Security.MustThrowIfAccessingRootButNotAllowed(usePortalRoot, out var exception))
            {
                throw exception;
            }

            Log.Add("check if feature enabled");
            if (Security.UserIsRestricted && !Eav.Configuration.Features.Enabled(FeaturesForRestrictedUsers))
            {
                throw HttpException.PermissionDenied(
                          $"low-permission users may not access this - {Eav.Configuration.Features.MsgMissingSome(FeaturesForRestrictedUsers)}");
            }

            if (string.IsNullOrEmpty(contentType) || string.IsNullOrEmpty(fieldName))
            {
                return(callLog(null, this));
            }

            Attribute = AttributeDefinition(appId, contentType, fieldName);
            if (!Security.FileTypeIsOkForThisField(out var exp))
            {
                throw exp;
            }
            return(callLog(null, this));
        }
Beispiel #14
0
        public IMultiPermissionCheck DoPreSaveSecurityCheck(int appId, IEnumerable <BundleWithHeader> items)
        {
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, items.Select(i => i.Header).ToList(), Log);

            if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var exp))
            {
                throw exp;
            }
            if (!permCheck.UserCanWriteAndPublicFormsEnabled(out exp))
            {
                throw exp;
            }

            // 2018-09-26 2dm
            // add test to verify that saving existing items is allowed

            Log.Add("passed security checks");
            return(permCheck);
        }
Beispiel #15
0
        public dynamic GetManyForEditing([FromBody] List <ItemIdentifier> items, int appId)
        {
            var wrapLog = Log.Call("GetManyForEditing", $"get many a#{appId}, items⋮{items.Count}");

            // before we start, we have to convert the indexes into something more useful, because
            // otherwise in content-list scenarios we don't have the type
            var appForSecurityChecks = App.LightWithoutData(new DnnTenant(PortalSettings), SystemRuntime.ZoneIdOfApp(appId), appId, Log);

            items = new SaveHelpers.ContentGroupList(SxcInstance, Log).ConvertListIndexToId(items, appForSecurityChecks);

            // to do full security check, we'll have to see what content-type is requested
            var permCheck = new MultiPermissionsTypes(SxcInstance, appId, items, Log);

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

            var list = new EntityApi(appId, Log).GetEntitiesForEditing(appId, items);

            // Reformat to the Entity-WithLanguage setup
            var listAsEwH = list.Select(p => new BundleWithHeader <EntityWithLanguages>
            {
                Header = p.Header,
                Entity = p.Entity != null
                    ? EntityWithLanguages.Build(appId, p.Entity)
                    : null
            }).ToList();

            // 2018-09-26 2dm
            // if we're giving items which already exist, then we must verify that edit/read is allowed.
            // important, this code is shared/duplicated in the UiController.Load
            if (list.Any(set => set.Entity != null))
            {
                if (!permCheck.EnsureAll(GrantSets.ReadSomething, out exception))
                {
                    throw exception;
                }
            }

            wrapLog($"will return items⋮{list.Count}");
            return(listAsEwH);
        }
Beispiel #16
0
        /// <summary>
        /// Initializes the object and performs all the initial security checks
        /// </summary>
        protected AdamState(IBlock block, int appId, string contentType, string field, Guid guid, bool usePortalRoot, ILog log)
            : base("Adm.State", log)
        {
            var callLog = Log.Call($"field:{field}, guid:{guid}");

            App         = Factory.Resolve <Apps.App>().Init(appId, log, block);
            Permissions = new MultiPermissionsTypes()
                          .Init(block.Context, App, contentType, Log);
            Block = block;

            // only do checks on field/guid if it's actually accessing that, if it's on the portal root, don't.
            UseTenantRoot = usePortalRoot;
            if (!usePortalRoot)
            {
                ItemField = field;
                ItemGuid  = guid;
            }

            Security = Factory.Resolve <SecurityChecksBase>().Init(this, usePortalRoot, Log);

            SecurityCheckHelpers.ThrowIfAccessingRootButNotAllowed(usePortalRoot, Security.UserIsRestricted);

            Log.Add("check if feature enabled");
            if (Security.UserIsRestricted && !ToSic.Eav.Configuration.Features.Enabled(FeaturesForRestrictedUsers))
            {
                throw HttpException.PermissionDenied(
                          $"low-permission users may not access this - {ToSic.Eav.Configuration.Features.MsgMissingSome(FeaturesForRestrictedUsers)}");
            }

            PrepCore(App, guid, field, usePortalRoot);

            if (string.IsNullOrEmpty(contentType) || string.IsNullOrEmpty(field))
            {
                return;
            }

            Attribute = Definition(appId, contentType, field);
            if (!Security.FileTypeIsOkForThisField(out var exp))
            {
                throw exp;
            }
            callLog(null);
        }
Beispiel #17
0
        public AllInOne Load([FromBody] List <ItemIdentifier> items, int appId)
        {
            // Security check
            var wraplog = Log.Call($"load many a#{appId}, items⋮{items.Count}");

            // 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 = new ContentGroupList(BlockBuilder, Log).ConvertListIndexToId(items, appIdentity);

            // 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 = new MultiPermissionsTypes(BlockBuilder, appId, items, Log);

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

            // load items - similar
            var result         = new AllInOne();
            var entityApi      = new EntityApi(appId, permCheck.EnsureAny(GrantSets.ReadDraft), Log);
            var typeRead       = entityApi.AppRead.ContentTypes;
            var list           = entityApi.GetEntitiesForEditing(appId, items);
            var jsonSerializer = new 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 exception))
                {
                    throw exception;
                }
            }

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

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

            // todo: ensure that sub-properties of the content-types are included
            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 = SystemController.FeatureListWithPermissionCheck(permCheck).ToList();

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