Keystone.js 6 access denied adminMeta - keystonejs

i want to seed data onConnect, but i have access denied, using this query :
{
keystone: keystone {
adminMeta {
lists {
key
description
label
singular
plural
path
fields {
path
}
}
}
}
i have this error even iam using sudo, context.sudo().graphql.raw :
[
Error: Access denied
at /Users/sidalitemkit/work/web/yet/wirxe/wirxe-app/node_modules/#keystone-next/admin-ui/system/dist/admin-ui.cjs.dev.js:552:19
at processTicksAndRejections (node:internal/process/task_queues:94:5)
at async Promise.all (index 0)
at async Promise.all (index 0) {
locations: [ [Object] ],
path: [ 'keystone', 'adminMeta' ]
}
]
here my config :
export default auth.withAuth(
config({
db: {
adapter: 'prisma_postgresql',
url:
'postgres://admin:aj093bf7l6jdx5hm#wirxe-app-database-do-user-9126376-0.b.db.ondigitalocean.com:25061/wirxepool?schema=public&pgbouncer=true&sslmode=require',
onConnect: initialiseData,
},
ui: {
isAccessAllowed: (context) => !!context.session?.data,
},
lists,
session: withItemData(
statelessSessions({
maxAge: sessionMaxAge,
secret: sessionSecret,
}),
{ User: 'email' },
),
}),
);
i figured out that when i do :
isAccessAllowed: (context) => true
it's working
any advice here

context.sudo() disabled access control. there could be some issue with your query. isAccessAllowed: (context) => true is related to admin-ui and not to the backend implementation of graphql. This could be a bug please open a bug in the repo. They whould be able to fix it quickly.
I do not see sample initialiseData to try myself. Also the graphql is designed as such if you try to access some non existing item then it may give you access denied error even though there is not access control (all access set to true).
There is also another api which is easier in creating the initial items. You should use new list api, available as context.sudo().lists.<ListName>.createOne or createMany like this
const user = await context.sudo().lists.User.createOne({
data: {
name: 'Alice',
posts: { create: [{ title: 'My first post' }] },
},
query: 'id name posts { id title }',
});
or
const users = await context.lists.User.createOne({
data: [
{
data: {
name: 'Alice',
posts: [{ create: { title: 'Alices first post' } }],
},
},
{
data: {
name: 'Bob',
posts: [{ create: { title: 'Bobs first post' } }],
},
},
],
query: 'id name posts { id title }',
});
for more details see List Items API and Database Items API in their preview documentation.

You can find a working example in keystonejs repository (blog)
You have to await and pass context to the initialiseData() method. The onConnect hook already provides this context for you
also, you can look for an argument like '--seed-data' so it's only run once
and run the code as:
keystone --seed-data
export default auth.withAuth(
config({
db: {
adapter: 'prisma_postgresql',
url:
'postgres://admin:aj093bf7l6jdx5hm#wirxe-app-database-do-user-9126376-0.b.db.ondigitalocean.com:25061/wirxepool?schema=public&pgbouncer=true&sslmode=require',
async onConnect(context) {
if (process.argv.includes('--seed-data')) {
await initialiseData(context);
}
},
},
ui: {
isAccessAllowed: (context) => !!context.session?.data,
},
lists,
session: withItemData(
statelessSessions({
maxAge: sessionMaxAge,
secret: sessionSecret,
}),
{ User: 'email' },
),
}),
);

Related

Adding Multiple connections to same user using Prisma in Nest Js

const studentClasses = await this.prisma.student.update({
where: {
id: dto.id,
},
data: {
classes: {
connect: [{ classId: CLASSIDHERE }, { classId: CLASSIDHERE }],
},
},
});
CLASSIDHERE: I want to change this dynamically because I want to connect all the classes that can be in the database?
Is there an easy to do this with prisma? Or I have to do a loop and run the connect...? I want to know best approach or maybe better...!
Thanks in advance.
As far as I understand your question, you'd like to connect many classes with a student. If yes,
I think you can simply connect by passing an array as you described
const classes = {
connect: [
{classId: ''}, {classId: ''}, ...
]
}
const studentClasses = await this.prisma.student.update({
where: { id: dto.id },
data: { classes },
});

Custom id generation for Redis-OM nodejs using provided entity data

for example:
const fooSchema = new Schema(Foo, {
userId: { type: 'number' },
channelId: { type: 'number' }
}, {
idStrategy: () => `${userId}${channelId}`
});
Is it possible to provide the idStrategy function with the entity data?

mongoose query return array instead of object

I faced a strange problem with the mongoose query. when I do db.collection.find() it should be return a object as expected. And I got so in mongo shell
When I do a similar query in my express router endpoint I got array instead of an object. Like
[
{
"dishes": [
"5eca615117611c0480320c12",
"5eca615117611c0480320c15"
],
"_id": "5ecae7eb2e746b312cfdf59e",
"user": "5ec644d06715633270d0414d",
...
}
]
which causes error in my frontend react application. Here is my schema in favorite model:
var favoriteSchema = new Schema(
{
dishes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Dish',
unique: true,
},
],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
},
{
timestamps: true,
}
);
And here is my express endpoint:
.get((req, res, next) => {
Favorites.find({})
.then(
(favorite) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json(favorite);
console.log(favorite);
},
(err) => next(err)
)
.catch((err) => next(err));
})
I heartily thank if anyone helps me to figure out this.
You might want to use findOne with mongoose, if you are looking for a single result or null. If you use find you expect more than one row as result.
Bare in mind you should handle the case where "favourite" is null (when you can't find the row you are looking for). At that point you might want to return a different response.
.find({parameter}) returns all the objects from database by the given parameter.

Issues with creating default broadcast (POST https://www.googleapis.com/youtube/v3/liveBroadcasts)

I'm trying to create default broadcast for my live stream with privacy set to 'unlisted' or 'private' bud it's always being created with privacy 'public', event though privacyStatus field is provided in request body:
REQUEST:
const res = await this.request(callback => youtube.liveBroadcasts.insert({
auth: auth,
part: 'snippet,contentDetails,status',
resource: {
snippet: {
title: "Some Title",
description: "Some description",
scheduledStartTime: "2020-03-11T12:08:43.087Z,
isDefaultBroadcast: true
},
status: {
privacyStatus: 'unlisted'
},
}
}, callback))
CHUNK OF RESPONSE:
data:
...
status:
{ lifeCycleStatus: 'ready',
privacyStatus: 'public',
recordingStatus: 'notRecording',
selfDeclaredMadeForKids: false }},
...
Is this a normal behaviour, or am i doing something wrong ? BTW update works fine.
If this is a normal behaviour it should be mentioned somewhere here:
https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/insert

Sencha Touch 2, before filter on the router, to check for user's auth state

I am developing a Sencha Touch 2 app with user authentication.
I use a token for authentication.
The logic.
Check is a token exists in local storage:
var tokenStore = Ext.getStore('TokenStore'),
token = tokenStore.getAt(0).get('token');
If there is a token, check if it's valid.
I am doing a read from a model which is connected to my API which, returns success or fail - depending on the token - if it's valid or not.
TestApp.model.CheckAuthModel.load(1, {
scope: this,
success: function(record) {
// Here, I know the token is valid
},
failure: function() {
console.log('failure');
},
callback: function(record) {
console.log('callback');
console.log();
}
});
And here is the router, which handles the logic for the views:
Ext.define("TestApp.controller.Router", {
extend: "Ext.app.Controller",
config: {
refs: {
HomeView: 'HomeView',
LoginView: 'LoginView',
ProductsView: 'ProductsView',
ProductsViewTwo: 'ProductsViewTwo'
},
routes: {
'': 'home',
'home' : 'home',
'login' : 'login',
'products' : 'products',
'testingtwo' : 'testingtwo'
}
},
home: function () {
console.log('TestApp.controller.Router home function');
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getHomeView();
if (comp === undefined) comp = Ext.create('TestApp.view.HomeView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function() {
initialItem.destroy();
}
}
});
},
login: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getLoginView();
if (comp === undefined) comp = Ext.create('TestApp.view.LoginView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function() {
initialItem.destroy();
}
}
});
},
products: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getProductsView();
if (comp === undefined) comp = Ext.create('TestApp.view.ProductsView');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function(){
initialItem.destroy();
}
}
});
},
testingtwo: function () {
var initialItem = Ext.Viewport.getActiveItem(),
comp = this.getProductsViewTwo();
if (comp === undefined) comp = Ext.create('TestApp.view.ProductsViewTwo');
Ext.Viewport.animateActiveItem(comp, {
type: 'slide',
listeners: {
animationend: function(){
initialItem.destroy();
}
}
});
},
launch: function() {
console.log('TestApp.controller.Router launch!');
}
});
Now, how can I link the router with the check auth model callback?
I want to know the auth state when the app reaches the router.
In other MVC frameworks, I could do a before filter, on the router, check for auth and handle the routes accordingly.
Can i do this in Sencha Touch 2?
Any ideas?
Hi I think this section in the documentation is exactly what you need:
before : Object
Provides a mapping of Controller functions to filter functions that are run before them when dispatched to from a route. These are usually used to run pre-processing functions like authentication before a certain function is executed. They are only called when dispatching from a route. Example usage:
Ext.define('MyApp.controller.Products', {
config: {
before: {
editProduct: 'authenticate'
},
routes: {
'product/edit/:id': 'editProduct'
}
},
//this is not directly because our before filter is called first
editProduct: function() {
//... performs the product editing logic
},
//this is run before editProduct
authenticate: function(action) {
MyApp.authenticate({
success: function() {
action.resume();
},
failure: function() {
Ext.Msg.alert('Not Logged In', "You can't do that, you're not logged in");
}
});
}
});
http://docs.sencha.com/touch/2.3.1/#!/api/Ext.app.Controller-cfg-before
Of course, it's still up to you to decide whether you should check every time or should cache the auth result for sometime.
Updated to answer comment below
Honestly, i am not sure how they was going to declare that static method Authenticate in Sencha (you would be able to do it normally through Javascript i think, i.e.: prototype).
But there are other better options to solve just that Authenticate function:
Just create a singleton class that handle utility stuffs.
http://docs.sencha.com/touch/2.3.1/#!/api/Ext.Class-cfg-singleton
If you really want to use MyApp, you can declare within the Ext.app.Application (in app.js). Then call it from the global instance MyApp.app.some_function(). I wouldn't exactly recommend this method because you change app.js, that might bring problem if you upgrade sencha touch.
You could implemented auth check in application's launch function or in your auth controller's init function and based on the response redirect the to appropriate url. Something like this:
TestApp.model.CheckAuthModel.load(1, {
scope: this,
success: function(record) {
this.redirectTo("home/");
},
failure: function() {
this.redirectTo("login/");
console.log('failure');
},
callback: function(record) {
console.log('callback');
console.log();
}
});