diff --git a/.editorconfig b/.editorconfig index ab561f3c56..435e72be69 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,4 @@ charset = utf-8 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true +spaces_around_brackets = both diff --git a/.eslintrc.json b/.eslintrc.json index afaeee7f71..be1e1314c4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,13 +7,46 @@ "parserOptions": { "ecmaVersion": 11 }, - "ignorePatterns": [ "modules/*/tests/*", "node_modules/*", "frontend/*"], + "ignorePatterns": [ + "modules/*/tests/*", + "node_modules/*", + "frontend/*" + ], "rules": { - "arrow-spacing": [ 2, { "before": true, "after": true } ], - "array-bracket-spacing": [ 2, "always" ], - "block-spacing": [ 2, "always" ], - "camelcase": [ 1, { "properties": "always" } ], - "space-in-parens": [ 2, "always" ], - "keyword-spacing": 2 + "arrow-spacing": [ + 2, + { + "before": true, + "after": true + } + ], + "array-bracket-spacing": [ + 2, + "always" + ], + "block-spacing": [ + 2, + "always" + ], + "camelcase": [ + 1, + { + "properties": "always" + } + ], + "space-in-parens": [ + 2, + "always" + ], + "keyword-spacing": 2, + "semi": "off", + "indent": [ + "error", + 2 + ], + "padded-blocks": [ + "error", + "never" + ] } -} +} \ No newline at end of file diff --git a/modules/core/graph/resolvers/branches.js b/modules/core/graph/resolvers/branches.js index a1dcdd1d3e..cdf63d0a6c 100644 --- a/modules/core/graph/resolvers/branches.js +++ b/modules/core/graph/resolvers/branches.js @@ -30,6 +30,8 @@ module.exports = { Stream: { async branches( parent, args, context, info ) { + if ( args.limit && args.limit > 100 ) + throw new UserInputError( 'Cannot return more than 100 items, please use pagination.' ) let { items, cursor, totalCount } = await getBranchesByStreamId( { streamId: parent.id, limit: args.limit, cursor: args.cursor } ) return { totalCount, cursor, items } diff --git a/modules/core/graph/resolvers/commits.js b/modules/core/graph/resolvers/commits.js index aa676faecc..acc7f0e2d6 100644 --- a/modules/core/graph/resolvers/commits.js +++ b/modules/core/graph/resolvers/commits.js @@ -32,6 +32,8 @@ module.exports = { Stream: { async commits( parent, args, context, info ) { + if ( args.limit && args.limit > 100 ) + throw new UserInputError( 'Cannot return more than 100 items, please use pagination.' ) let { commits: items, cursor } = await getCommitsByStreamId( { streamId: parent.id, limit: args.limit, cursor: args.cursor } ) let totalCount = await getCommitsTotalCountByStreamId( { streamId: parent.id } ) @@ -47,9 +49,10 @@ module.exports = { User: { async commits( parent, args, context, info ) { - let publicOnly = context.userId !== parent.id let totalCount = await getCommitsTotalCountByUserId( { userId: parent.id } ) + if ( args.limit && args.limit > 100 ) + throw new UserInputError( 'Cannot return more than 100 items, please use pagination.' ) let { commits: items, cursor } = await getCommitsByUserId( { userId: parent.id, limit: args.limit, cursor: args.cursor, publicOnly } ) return { items, cursor, totalCount } @@ -58,6 +61,8 @@ module.exports = { }, Branch: { async commits( parent, args, context, info ) { + if ( args.limit && args.limit > 100 ) + throw new UserInputError( 'Cannot return more than 100 items, please use pagination.' ) let { commits, cursor } = await getCommitsByBranchId( { branchId: parent.id, limit: args.limit, cursor: args.cursor } ) let totalCount = await getCommitsTotalCountByBranchId( { branchId: parent.id } ) diff --git a/modules/core/graph/resolvers/streams.js b/modules/core/graph/resolvers/streams.js index df53641edb..b37d508680 100644 --- a/modules/core/graph/resolvers/streams.js +++ b/modules/core/graph/resolvers/streams.js @@ -22,6 +22,17 @@ module.exports = { let stream = await getStream( { streamId: args.id } ) return stream + }, + async streams( parent, args, context, info ) { + await validateScopes( context.scopes, 'streams:read' ) + + if ( args.limit && args.limit > 100 ) + throw new UserInputError( 'Cannot return more than 100 items, please use pagination.' ) + + let totalCount = await getUserStreamsCount( {userId: context.userId, publicOnly: false, searchQuery: args.query} ) + + let {cursor, streams} = await getUserStreams( {userId: context.userId, limit: args.limit, cursor: args.cursor, publicOnly: false, searchQuery: args.query} ) + return {totalCount, cursor: cursor, items: streams} } }, Stream: { @@ -35,7 +46,9 @@ module.exports = { User: { async streams( parent, args, context, info ) { - // Return only the user's public streams if parent.id !== context.userId + if ( args.limit && args.limit > 100 ) + throw new UserInputError( 'Cannot return more than 100 items, please use pagination.' ) + // Return only the user's public streams if parent.id !== context.userId let publicOnly = parent.id !== context.userId let totalCount = await getUserStreamsCount( { userId: parent.id, publicOnly } ) diff --git a/modules/core/graph/resolvers/user.js b/modules/core/graph/resolvers/users.js similarity index 74% rename from modules/core/graph/resolvers/user.js rename to modules/core/graph/resolvers/users.js index cb5a6853d4..2f5dfc66c7 100644 --- a/modules/core/graph/resolvers/user.js +++ b/modules/core/graph/resolvers/users.js @@ -1,7 +1,7 @@ 'use strict' const appRoot = require( 'app-root-path' ) const { ApolloError, AuthenticationError, UserInputError } = require( 'apollo-server-express' ) -const { createUser, getUser, getUserByEmail, getUserRole, updateUser, deleteUser, validatePasssword } = require( '../../services/users' ) +const { createUser, getUser, getUserByEmail, getUserRole, updateUser, deleteUser, searchUsers, validatePasssword } = require( '../../services/users' ) const { createPersonalAccessToken, createAppToken, revokeToken, revokeTokenById, validateToken, getUserTokens } = require( '../../services/tokens' ) const { validateServerRole, validateScopes, authorizeResolver } = require( `${appRoot}/modules/shared` ) const setupCheck = require( `${appRoot}/setupcheck` ) @@ -10,12 +10,11 @@ const zxcvbn = require( 'zxcvbn' ) module.exports = { Query: { - async _( ) { + async _() { return `Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn.` }, async user( parent, args, context, info ) { - await validateServerRole( context, 'server:user' ) if ( !args.id ) @@ -30,6 +29,22 @@ module.exports = { return await getUser( args.id || context.userId ) }, + async userSearch( parent, args, context, info ) { + await validateServerRole( context, 'server:user' ) + await validateScopes( context.scopes, 'profile:read' ) + await validateScopes( context.scopes, 'users:read' ) + + if ( args.query.length < 3 ) + throw new UserInputError( 'Search query must be at least 3 carachters.' ) + + + if ( args.limit && args.limit > 100 ) + throw new UserInputError( 'Cannot return more than 100 items, please use pagination.' ) + + let {cursor, users} = await searchUsers( args.query, args.limit, args.cursor ) + return {cursor: cursor, items: users} + }, + async userPwdStrength( parent, args, context, info ) { let res = zxcvbn( args.pwd ) return { score: res.score, feedback: res.feedback } @@ -64,6 +79,8 @@ module.exports = { }, + + Mutation: { async userEdit( parent, args, context, info ) { await validateServerRole( context, 'server:user' ) @@ -71,4 +88,4 @@ module.exports = { return true } } -} +} \ No newline at end of file diff --git a/modules/core/graph/schemas/branchesAndCommits.graphql b/modules/core/graph/schemas/branchesAndCommits.graphql index 5fb953dd03..c15b4a59f9 100644 --- a/modules/core/graph/schemas/branchesAndCommits.graphql +++ b/modules/core/graph/schemas/branchesAndCommits.graphql @@ -1,12 +1,12 @@ extend type Stream { - commits( limit: Int! = 20, cursor: String ): CommitCollection + commits( limit: Int! = 25, cursor: String ): CommitCollection commit( id: String! ): Commit - branches( limit: Int! = 100, cursor: String ): BranchCollection + branches( limit: Int! = 25, cursor: String ): BranchCollection branch( name: String! ): Branch } extend type User { - commits( limit: Int! = 20, cursor: String ): CommitCollectionUser + commits( limit: Int! = 25, cursor: String ): CommitCollectionUser } type Branch { @@ -14,7 +14,7 @@ type Branch { name: String! author: User! description: String! - commits( limit: Int! = 20, cursor: String ): CommitCollection + commits( limit: Int! = 25, cursor: String ): CommitCollection } type Commit { diff --git a/modules/core/graph/schemas/streams.graphql b/modules/core/graph/schemas/streams.graphql index 570d69f511..a4893dfffe 100644 --- a/modules/core/graph/schemas/streams.graphql +++ b/modules/core/graph/schemas/streams.graphql @@ -1,5 +1,9 @@ extend type Query { stream( id: String! ): Stream + """ + All the streams of the current user, pass in the `query` parameter to seach by name, description or ID. + """ + streams( query: String!, limit: Int! = 25, cursor: String ): StreamCollection } type Stream { @@ -16,7 +20,7 @@ extend type User { """ All the streams that a user has access to. """ - streams( limit: Int! = 20, cursor: String ): StreamCollectionUser + streams( limit: Int! = 25, cursor: String ): StreamCollection } type StreamCollaborator { @@ -25,12 +29,13 @@ type StreamCollaborator { role: String! } -type StreamCollectionUser { +type StreamCollection { totalCount: Int! cursor: String items: [ Stream ] } + extend type Mutation { """ Creates a new stream. diff --git a/modules/core/graph/schemas/user.graphql b/modules/core/graph/schemas/user.graphql index 355ec20fd8..33cc389908 100644 --- a/modules/core/graph/schemas/user.graphql +++ b/modules/core/graph/schemas/user.graphql @@ -3,6 +3,7 @@ extend type Query { Gets the profile of a user. If no id argument is provided, will return the current authenticated user's profile (as extracted from the authorization header). """ user( id: String ): User + userSearch( query: String!, limit: Int! = 25, cursor: String ): UserSearchResultCollection userPwdStrength( pwd: String! ): JSONObject } @@ -22,6 +23,21 @@ type User { role: String } +type UserSearchResultCollection { + cursor: String + items: [ UserSearchResult ] +} + +type UserSearchResult { + id: String! + username: String + name: String + bio: String + company: String + avatar: String + verified: Boolean +} + extend type Mutation { """ Edits a user's profile. diff --git a/modules/core/migrations/002-2020-05-18-scopes.js b/modules/core/migrations/002-2020-05-18-scopes.js index 7a879c3fb6..2def799c53 100644 --- a/modules/core/migrations/002-2020-05-18-scopes.js +++ b/modules/core/migrations/002-2020-05-18-scopes.js @@ -6,50 +6,50 @@ exports.up = async knex => { debug( 'Setting up core module scopes.' ) let coreModuleScopes = [ { - name: 'server:setup', - description: 'Edit server information.' - }, - { - name: 'tokens:read', - description: `Access your api tokens.` - }, - { - name: 'tokens:write', - description: `Create and delete api tokens on your behalf.` - }, - { - name: 'apps:authorize', - description: 'Grant third party applications access rights on your behalf to the api.' - }, - { - name: 'apps:create', - description: 'Register a third party application.' - }, - { - name: 'streams:read', - description: 'Read your streams & and any associated information (branches, tags, comments, objects, etc.)' - }, - { - name: 'streams:write', - description: 'Create streams on your behalf and read your streams & any associated information (any associated information (branches, tags, comments, objects, etc.)' - }, - { - name: 'profile:read', - description: `Read your profile information` - }, - { - name: 'profile:email', - description: `Access your email.` - }, + name: 'server:setup', + description: 'Edit server information.' + }, + { + name: 'tokens:read', + description: `Access your api tokens.` + }, + { + name: 'tokens:write', + description: `Create and delete api tokens on your behalf.` + }, + { + name: 'apps:authorize', + description: 'Grant third party applications access rights on your behalf to the api.' + }, + { + name: 'apps:create', + description: 'Register a third party application.' + }, + { + name: 'streams:read', + description: 'Read your streams & and any associated information (branches, tags, comments, objects, etc.)' + }, + { + name: 'streams:write', + description: 'Create streams on your behalf and read your streams & any associated information (any associated information (branches, tags, comments, objects, etc.)' + }, + { + name: 'profile:read', + description: `Read your profile information` + }, + { + name: 'profile:email', + description: `Access your email.` + }, - { - name: 'users:read', - description: `Read other users' profile on your behalf.` - }, - { - name: 'users:email', - description: 'Access the emails of other users.' - } + { + name: 'users:read', + description: `Read other users' profile on your behalf.` + }, + { + name: 'users:email', + description: 'Access the emails of other users.' + } ] await knex( 'scopes' ).insert( coreModuleScopes ) diff --git a/modules/core/services/branches.js b/modules/core/services/branches.js index 435c3fe5b9..3434877d34 100644 --- a/modules/core/services/branches.js +++ b/modules/core/services/branches.js @@ -10,7 +10,6 @@ const BranchCommits = ( ) => knex( 'branch_commits' ) module.exports = { async createBranch( { name, description, streamId, authorId } ) { - let branch = {} branch.id = crs( { length: 10 } ) branch.streamId = streamId @@ -32,7 +31,7 @@ module.exports = { }, async getBranchesByStreamId( { streamId, limit, cursor } ) { - limit = limit || 100 + limit = limit || 25 let query = Branches( ).select( '*' ).where( { streamId: streamId } ) if ( cursor ) diff --git a/modules/core/services/commits.js b/modules/core/services/commits.js index 1c4acb0a56..2d3f035c52 100644 --- a/modules/core/services/commits.js +++ b/modules/core/services/commits.js @@ -15,7 +15,6 @@ const { getBranchesByStreamId, getBranchByNameAndStreamId } = require( './branch module.exports = { async createCommitByBranchId( { streamId, branchId, objectId, authorId, message, previousCommitIds } ) { - // Create main table entry let [ id ] = await Commits( ).returning( 'id' ).insert( { id: crs( { length: 10 } ), @@ -84,7 +83,7 @@ module.exports = { }, async getCommitsByBranchId( { branchId, limit, cursor } ) { - limit = limit || 20 + limit = limit || 25 let query = BranchCommits( ).columns( [ { id: 'commitId' }, 'message', 'referencedObject', { authorName: 'name' }, { authorId: 'users.id' }, 'commits.createdAt' ] ).select( ) .join( 'commits', 'commits.id', 'branch_commits.commitId' ) .join( 'users', 'commits.author', 'users.id' ) @@ -124,7 +123,7 @@ module.exports = { * @return {[type]} [description] */ async getCommitsByStreamId( { streamId, limit, cursor } ) { - limit = limit || 20 + limit = limit || 25 let query = StreamCommits( ) .columns( [ { id: 'commitId' }, 'message', 'referencedObject', { authorName: 'name' }, { authorId: 'users.id' }, 'commits.createdAt' ] ).select( ) .join( 'commits', 'commits.id', 'stream_commits.commitId' ) @@ -142,15 +141,15 @@ module.exports = { }, async getCommitsByUserId( { userId, limit, cursor, publicOnly } ) { - limit = limit || 20 + limit = limit || 25 publicOnly = publicOnly !== false let query = Commits( ) - .columns( [ { id: 'commitId' }, 'message', 'referencedObject', 'commits.createdAt', { streamId: 'stream_commits.streamId' }, { streamName: 'streams.name' } ] ).select( ) - .join( 'stream_commits', 'commits.id', 'stream_commits.commitId' ) - .join( 'streams', 'stream_commits.streamId', 'streams.id' ) - .where( 'author', userId ) + .columns( [ { id: 'commitId' }, 'message', 'referencedObject', 'commits.createdAt', { streamId: 'stream_commits.streamId' }, { streamName: 'streams.name' } ] ).select( ) + .join( 'stream_commits', 'commits.id', 'stream_commits.commitId' ) + .join( 'streams', 'stream_commits.streamId', 'streams.id' ) + .where( 'author', userId ) if ( publicOnly ) query.andWhere( 'streams.isPublic', true ) diff --git a/modules/core/services/streams.js b/modules/core/services/streams.js index 3add285096..02cdce03e6 100644 --- a/modules/core/services/streams.js +++ b/modules/core/services/streams.js @@ -89,8 +89,8 @@ module.exports = { return await Streams( ).where( { id: streamId } ).del( ) }, - async getUserStreams( { userId, limit, cursor, publicOnly } ) { - limit = limit || 100 + async getUserStreams( { userId, limit, cursor, publicOnly, searchQuery } ) { + limit = limit || 25 publicOnly = publicOnly !== false //defaults to true if not provided let query = Acl( ) @@ -104,14 +104,20 @@ module.exports = { if ( publicOnly ) query.andWhere( 'streams.isPublic', true ) + if ( searchQuery ) + query.andWhere( function () { + this.where( 'name', 'ILIKE', `%${ searchQuery }%` ) + .orWhere( 'description', 'ILIKE', `%${searchQuery}%` ) + .orWhere( 'id', 'ILIKE', `%${searchQuery}%` ) //potentially useless? + } ) + query.orderBy( 'streams.updatedAt', 'desc' ).limit( limit ) let rows = await query return { streams: rows, cursor: rows.length > 0 ? rows[ rows.length - 1 ].updatedAt.toISOString( ) : null } }, - async getUserStreamsCount( { userId, publicOnly } ) { - + async getUserStreamsCount( {userId, publicOnly, searchQuery } ) { publicOnly = publicOnly !== false //defaults to true if not provided let query = Acl( ).count( ) @@ -121,6 +127,13 @@ module.exports = { if ( publicOnly ) query.andWhere( 'streams.isPublic', true ) + if ( searchQuery ) + query.andWhere( function () { + this.where( 'name', 'ILIKE', `%${searchQuery}%` ) + .orWhere( 'description', 'ILIKE', `%${searchQuery}%` ) + .orWhere( 'id', 'ILIKE', `%${searchQuery}%` ) //potentially useless? + } ) + let [ res ] = await query return parseInt( res.count ) }, @@ -128,10 +141,10 @@ module.exports = { async getStreamUsers( { streamId } ) { let query = Acl( ).columns( { role: 'stream_acl.role' }, 'id', 'name' ).select( ) - .where( { resourceId: streamId } ) - .rightJoin( 'users', { 'users.id': 'stream_acl.userId' } ) - .select( 'stream_acl.role', 'username', 'name', 'id' ) - .orderBy( 'stream_acl.role' ) + .where( { resourceId: streamId } ) + .rightJoin( 'users', { 'users.id': 'stream_acl.userId' } ) + .select( 'stream_acl.role', 'username', 'name', 'id' ) + .orderBy( 'stream_acl.role' ) return await query } diff --git a/modules/core/services/users.js b/modules/core/services/users.js index 4473d051ac..c3628f8722 100644 --- a/modules/core/services/users.js +++ b/modules/core/services/users.js @@ -4,73 +4,73 @@ const crs = require( 'crypto-random-string' ) const appRoot = require( 'app-root-path' ) const knex = require( `${appRoot}/db/knex` ) -const Users = ( ) => knex( 'users' ) -const ServerRoles = ( ) => knex( 'server_acl' ) +const Users = () => knex( 'users' ) +const Acl = () => knex( 'server_acl' ) module.exports = { /* - Users + Users - */ + */ async createUser( user ) { - let [ { count } ] = await ServerRoles( ).where( { role: 'server:admin' } ).count( ) + let [ {count} ] = await Acl().where( {role: 'server:admin'} ).count() - user.id = crs( { length: 10 } ) + user.id = crs( {length: 10} ) if ( user.password ) { user.passwordDigest = await bcrypt.hash( user.password, 10 ) } delete user.password - let usr = await Users( ).select( 'id' ).where( { email: user.email } ).first( ) + let usr = await Users().select( 'id' ).where( {email: user.email} ).first() if ( usr ) throw new Error( 'Email taken. Try logging in?' ) - let res = await Users( ).returning( 'id' ).insert( user ) + let res = await Users().returning( 'id' ).insert( user ) if ( parseInt( count ) === 0 ) { - await ServerRoles( ).insert( { userId: res[ 0 ], role: 'server:admin' } ) + await Acl().insert( {userId: res[0], role: 'server:admin'} ) } else { - await ServerRoles( ).insert( { userId: res[ 0 ], role: 'server:user' } ) + await Acl().insert( {userId: res[0], role: 'server:user'} ) } - return res[ 0 ] + return res[0] }, - async findOrCreateUser( { user, rawProfile } ) { - let existingUser = await Users( ).select( 'id' ).where( { email: user.email } ).first( ) + async findOrCreateUser( {user, rawProfile} ) { + let existingUser = await Users().select( 'id' ).where( {email: user.email} ).first() if ( existingUser ) return existingUser - user.password = crs( { length: 20 } ) + user.password = crs( {length: 20} ) user.verified = true // because we trust the external identity provider, no? - return { id: await module.exports.createUser( user ) } + return {id: await module.exports.createUser( user )} }, - async getUserById( { userId } ) { - let user = await Users( ).where( { id: userId } ).select( '*' ).first( ) + async getUserById( {userId} ) { + let user = await Users().where( {id: userId} ).select( '*' ).first() delete user.passwordDigest return user }, // TODO: deprecate async getUser( id ) { - let user = await Users( ).where( { id: id } ).select( '*' ).first( ) + let user = await Users().where( {id: id} ).select( '*' ).first() delete user.passwordDigest return user }, - async getUserByEmail( { email } ) { - let user = await Users( ).where( { email: email } ).select( '*' ).first( ) + async getUserByEmail( {email} ) { + let user = await Users().where( {email: email} ).select( '*' ).first() delete user.passwordDigest return user }, async getUserRole( id ) { - let { role } = await ServerRoles( ).where( { userId: id } ).select( 'role' ).first( ) + let {role} = await Acl().where( {userId: id} ).select( 'role' ).first() return role }, @@ -79,15 +79,35 @@ module.exports = { delete user.passwordDigest delete user.password delete user.email - await Users( ).where( { id: id } ).update( user ) + await Users().where( {id: id} ).update( user ) }, - async validatePasssword( { email, password } ) { - let { passwordDigest } = await Users( ).where( { email: email } ).select( 'passwordDigest' ).first( ) + async searchUsers( searchQuery, limit, cursor ) { + limit = limit || 25 + + let query = Users() + .select( 'id', 'username', 'name', 'bio', 'company', 'verified', 'avatar', 'createdAt' ) + .where( queryBuilder => { + queryBuilder.where( {email: searchQuery} ) //match full email or partial username / name + queryBuilder.orWhere( 'username', 'ILIKE', `%${searchQuery}%` ) + queryBuilder.orWhere( 'name', 'ILIKE', `%${searchQuery}%` ) + } ) + + if ( cursor ) + query.andWhere( 'users.createdAt', '<', cursor ) + + query.orderBy( 'users.createdAt', 'desc' ).limit( limit ) + + let rows = await query + return {users: rows, cursor: rows.length > 0 ? rows[rows.length - 1].createdAt.toISOString() : null} + }, + + async validatePasssword( {email, password} ) { + let {passwordDigest} = await Users().where( {email: email} ).select( 'passwordDigest' ).first() return bcrypt.compare( password, passwordDigest ) }, async deleteUser( id ) { throw new Error( 'not implemented' ) } -} +} \ No newline at end of file diff --git a/modules/core/tests/streams.spec.js b/modules/core/tests/streams.spec.js index 828c182ec4..a3570bebaf 100644 --- a/modules/core/tests/streams.spec.js +++ b/modules/core/tests/streams.spec.js @@ -65,13 +65,20 @@ describe( 'Streams', ( ) => { expect( stream.description ).to.equal( 'Wooot' ) } ) - it( 'Should get all streams for a user', async ( ) => { + it( 'Should get all streams of a user', async ( ) => { let { streams, cursor } = await getUserStreams( { userId: userOne.id } ) // console.log( res ) expect( streams ).to.have.lengthOf( 2 ) expect( cursor ).to.exist } ) + it('Should search all streams of a user', async () => { + let {streams, cursor} = await getUserStreams({userId: userOne.id, searchQuery: "woo"}) + // console.log( res ) + expect(streams).to.have.lengthOf(1) + expect(cursor).to.exist + }) + it( 'Should delete a stream', async ( ) => { const id = await createStream( { name: 'mayfly', description: 'wonderful', ownerId: userOne.id } ) let all = await getUserStreams( { userId: userOne.id } ) diff --git a/modules/core/tests/users.spec.js b/modules/core/tests/users.spec.js index d41a73909f..aaf30dd78f 100644 --- a/modules/core/tests/users.spec.js +++ b/modules/core/tests/users.spec.js @@ -11,7 +11,7 @@ chai.use( chaiHttp ) const knex = require( `${appRoot}/db/knex` ) -const { createUser, getUser, updateUser, deleteUser, validatePasssword } = require( '../services/users' ) +const {createUser, getUser, searchUsers, updateUser, deleteUser, validatePasssword } = require( '../services/users' ) const { createPersonalAccessToken, createAppToken, revokeToken, revokeTokenById, validateToken, getUserTokens } = require( '../services/tokens' ) describe( 'Actors & Tokens', ( ) => { @@ -61,6 +61,12 @@ describe( 'Actors & Tokens', ( ) => { expect( actor ).to.not.have.property( 'passwordDigest' ) } ) + it('Should search and get an users', async () => { + let {users} = await searchUsers("gates", 20, null) + expect(users).to.have.lengthOf(1) + expect(users[0].name).to.equal("Bill Gates") + }) + it( 'Should update an actor', async ( ) => { let updatedActor = { ...myTestActor } updatedActor.username = 'didimitrie' diff --git a/readme.md b/readme.md index 89d2341e5f..6a1b2153c0 100644 --- a/readme.md +++ b/readme.md @@ -28,6 +28,14 @@ When pushing commits to this repo, please follow the following guidelines: - Install [commitizen](https://www.npmjs.com/package/commitizen#commitizen-for-contributors) globally (`npm i -g commitizen`). - When ready to commit, type in the commandline `git cz` & follow the prompts. +- Install eslint globally `npm i -g eslint` + - if using VS code install the `eslint` extension + - we also recommend setting it to run on save by adding the following VS Code setting + ``` + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + } + ``` ## Modules