@@ -958,18 +958,21 @@ export class DatabaseConnection extends events.EventEmitter {
958958 Logger . otel . endSpan ( span ) ;
959959 }
960960 }
961- /**
961+ /**
962962 * Get a single item based on id
963963 * @param {string } id Id to search for
964964 * @param {string } collectionname Collection to search
965965 * @param {string } jwt JWT of user who is making the query, to limit results based on permissions
966966 * @returns Promise<T>
967967 */
968- async getbyid < T extends Base > ( id : string , collectionname : string , jwt : string , decrypt : boolean , parent : Span ) : Promise < T > {
969- const span : Span = Logger . otel . startSubSpan ( "db.getbyid" , parent ) ;
968+ async GetOne < T extends Base > ( options : { query ?: object , collectionname : string , orderby ?: object , jwt ?: string , decrypt ?: boolean } , parent : Span ) : Promise < T > {
969+ const span : Span = Logger . otel . startSubSpan ( "db.GetOne" , parent ) ;
970+ if ( NoderedUtil . IsNullUndefinded ( options . jwt ) ) options . jwt = Crypt . rootToken ( ) ;
971+ if ( NoderedUtil . IsNullUndefinded ( options . decrypt ) ) options . decrypt = true ;
972+ if ( NoderedUtil . IsNullUndefinded ( options . query ) ) options . query = { } ;
973+ const { query, collectionname, orderby, jwt, decrypt } = options ;
970974 try {
971- if ( id === null || id === undefined || id === "" ) { throw Error ( "Id cannot be null" ) ; }
972- const arr : T [ ] = await this . query < T > ( { query : { _id : id } , top : 1 , collectionname, jwt, decrypt } , span ) ;
975+ const arr : T [ ] = await this . query < T > ( { query, collectionname, orderby, jwt, decrypt } , span ) ;
973976 if ( arr === null || arr . length === 0 ) { return null ; }
974977 return arr [ 0 ] ;
975978 } catch ( error ) {
@@ -980,19 +983,18 @@ export class DatabaseConnection extends events.EventEmitter {
980983 }
981984 }
982985 /**
983- * Get a single item based on name
984- * @param {string } name Name to search for
986+ * Get a single item based on id
987+ * @param {string } id Id to search for
985988 * @param {string } collectionname Collection to search
986989 * @param {string } jwt JWT of user who is making the query, to limit results based on permissions
987990 * @returns Promise<T>
988991 */
989- async getbyname < T extends Base > ( name : string , collectionname : string , jwt : string , decrypt : boolean , parent : Span ) : Promise < T > {
992+ async getbyid < T extends Base > ( id : string , collectionname : string , jwt : string , decrypt : boolean , parent : Span ) : Promise < T > {
990993 const span : Span = Logger . otel . startSubSpan ( "db.getbyid" , parent ) ;
991994 try {
992- if ( name === null || name === undefined || name === "" ) { throw Error ( "Name cannot be null" ) ; }
993- const arr : T [ ] = await this . query < T > ( { query : { name } , top : 1 , collectionname, jwt, decrypt } , span ) ;
994- if ( arr === null || arr . length === 0 ) { return null ; }
995- return arr [ 0 ] ;
995+ if ( id === null || id === undefined || id === "" ) { throw Error ( "Id cannot be null" ) ; }
996+ const query = { _id : id } ;
997+ return this . GetOne ( { query, collectionname, jwt, decrypt } , span )
996998 } catch ( error ) {
997999 span ?. recordException ( error ) ;
9981000 throw error ;
@@ -1259,7 +1261,7 @@ export class DatabaseConnection extends events.EventEmitter {
12591261 if ( user . dblocked && ! user . HasRoleName ( "admins" ) ) throw new Error ( "Access denied (db locked) could be due to hitting quota limit for " + user . username ) ;
12601262 span ?. addEvent ( "ensureResource" ) ;
12611263 item = this . ensureResource ( item , collectionname ) ;
1262- if ( ! await this . CheckEntityRestriction ( user , collectionname , item , span ) ) {
1264+ if ( user . _id != WellknownIds . root && ! await this . CheckEntityRestriction ( user , collectionname , item , span ) ) {
12631265 throw Error ( "Create " + item . _type + " access denied" ) ;
12641266 }
12651267 span ?. addEvent ( "traversejsonencode" ) ;
@@ -1882,7 +1884,7 @@ export class DatabaseConnection extends events.EventEmitter {
18821884 q . item . _version = original . _version ;
18831885 }
18841886 q . item = this . ensureResource ( q . item , q . collectionname ) ;
1885- if ( original . _type != q . item . _type && ! await this . CheckEntityRestriction ( user , q . collectionname , q . item , span ) ) {
1887+ if ( user . _id != WellknownIds . root && original . _type != q . item . _type && ! await this . CheckEntityRestriction ( user , q . collectionname , q . item , span ) ) {
18861888 throw Error ( "Create " + q . item . _type + " access denied" ) ;
18871889 }
18881890 const hasUser : Ace = q . item . _acl . find ( e => e . _id === user . _id ) ;
@@ -2286,6 +2288,9 @@ export class DatabaseConnection extends events.EventEmitter {
22862288 } ) ;
22872289 } ,
22882290 } ) ;
2291+ async InsertOrUpdateOne < T extends Base > ( q : InsertOrUpdateOneMessage , parent : Span ) : Promise < InsertOrUpdateOneMessage > {
2292+ return this . _InsertOrUpdateOne ( q , parent ) ;
2293+ }
22892294 private static InsertOrUpdateOneSemaphore = DatabaseConnection . Semaphore ( 1 ) ;
22902295 /**
22912296 * Insert or Update depending on document allready exists.
@@ -2297,7 +2302,7 @@ export class DatabaseConnection extends events.EventEmitter {
22972302 * @param {string } jwt JWT of user who is doing the update, ensuring rights
22982303 * @returns Promise<T>
22992304 */
2300- async InsertOrUpdateOne < T extends Base > ( q : InsertOrUpdateOneMessage , parent : Span ) : Promise < InsertOrUpdateOneMessage > {
2305+ async _InsertOrUpdateOne < T extends Base > ( q : InsertOrUpdateOneMessage , parent : Span ) : Promise < InsertOrUpdateOneMessage > {
23012306 const span : Span = Logger . otel . startSubSpan ( "db.InsertOrUpdateOne" , parent ) ;
23022307 try {
23032308 await DatabaseConnection . InsertOrUpdateOneSemaphore . down ( ) ;
@@ -2316,7 +2321,13 @@ export class DatabaseConnection extends events.EventEmitter {
23162321 query = { _id : q . item . _id } ;
23172322 }
23182323 }
2319- const user : TokenUser = await Crypt . verityToken ( q . jwt ) ;
2324+ let user : TokenUser = ( q as any ) . user ;
2325+ if ( NoderedUtil . IsNullUndefinded ( user ) ) {
2326+ user = await Crypt . verityToken ( q . jwt ) ;
2327+ } else {
2328+ delete ( q as any ) . user ;
2329+ }
2330+
23202331 if ( user . dblocked && ! user . HasRoleName ( "admins" ) ) throw new Error ( "Access denied (db locked) could be due to hitting quota limit for " + user . username ) ;
23212332 let exists : Base [ ] = [ ] ;
23222333 if ( query != null ) {
@@ -2375,6 +2386,51 @@ export class DatabaseConnection extends events.EventEmitter {
23752386 Logger . otel . endSpan ( span ) ;
23762387 }
23772388 }
2389+ async InsertOrUpdateMany < T extends Base > ( items : T [ ] , collectionname : string , uniqeness : string , skipresults : boolean , w : number , j : boolean , jwt : string , parent : Span ) : Promise < T [ ] > {
2390+ const span : Span = Logger . otel . startSubSpan ( "db.InsertOrUpdateMany" , parent ) ;
2391+ let result : T [ ] = [ ] ;
2392+ try {
2393+ if ( NoderedUtil . IsNullUndefinded ( items ) || items . length == 0 ) { throw Error ( "Cannot create null item" ) ; }
2394+ if ( NoderedUtil . IsNullEmpty ( jwt ) ) {
2395+ throw new Error ( "jwt is null" ) ;
2396+ }
2397+ await this . connect ( span ) ;
2398+ const user = await Crypt . verityToken ( jwt ) ;
2399+ if ( user . dblocked && ! user . HasRoleName ( "admins" ) ) throw new Error ( "Access denied (db locked) could be due to hitting quota limit for " + user . username ) ;
2400+ span ?. setAttribute ( "collection" , collectionname ) ;
2401+ span ?. setAttribute ( "username" , user . username ) ;
2402+ let inserted = 0 ;
2403+ let updated = 0 ;
2404+ for ( var i = 0 ; i < items . length ; i ++ ) {
2405+ const item = items [ i ] ;
2406+ var q = new InsertOrUpdateOneMessage ( ) ;
2407+ ( q as any ) . user = user ;
2408+ q . collectionname = collectionname ; q . item = item ; q . j = j ;
2409+ q . w = w ; q . jwt = jwt ; q . uniqeness = uniqeness ;
2410+ var res = await this . _InsertOrUpdateOne ( q , span ) ;
2411+ if ( res && res . opresult ) {
2412+ if ( res . opresult . modifiedCount == 1 ) {
2413+ updated ++ ;
2414+ } else {
2415+ inserted ++ ;
2416+ }
2417+ } else {
2418+ if ( item . _id != res . result . _id ) inserted ++ ;
2419+ if ( item . _id == res . result . _id ) updated ++ ;
2420+ }
2421+ if ( ! skipresults ) result . push ( res . result ) ;
2422+ }
2423+ Logger . instanse . info ( "DatabaseConnection" , "InsertOrUpdateMany" , "[" + user . username + "][" + collectionname + "] inserted " + inserted + " items and updated " + updated + " items in database" ) ;
2424+ } catch ( error ) {
2425+ Logger . instanse . error ( "DatabaseConnection" , "InsertOrUpdateMany" , error ) ;
2426+ span ?. recordException ( error ) ;
2427+ throw error ;
2428+ }
2429+ finally {
2430+ Logger . otel . endSpan ( span ) ;
2431+ }
2432+ return result ;
2433+ }
23782434 private async _DeleteFile ( id : string ) : Promise < void > {
23792435 return new Promise < void > ( async ( resolve , reject ) => {
23802436 try {
0 commit comments