Add signup approval API tests
This commit is contained in:
parent
3e5716dd3a
commit
b379759f55
|
@ -79,6 +79,7 @@ describe('Test config API validators', function () {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
limit: 5,
|
limit: 5,
|
||||||
|
requiresApproval: false,
|
||||||
requiresEmailVerification: false,
|
requiresEmailVerification: false,
|
||||||
minimumAge: 16
|
minimumAge: 16
|
||||||
},
|
},
|
||||||
|
@ -313,6 +314,7 @@ describe('Test config API validators', function () {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
limit: 5,
|
limit: 5,
|
||||||
|
requiresApproval: true,
|
||||||
requiresEmailVerification: true
|
requiresEmailVerification: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,14 @@
|
||||||
|
|
||||||
import { MockSmtpServer } from '@server/tests/shared'
|
import { MockSmtpServer } from '@server/tests/shared'
|
||||||
import { HttpStatusCode } from '@shared/models'
|
import { HttpStatusCode } from '@shared/models'
|
||||||
import { cleanupTests, ContactFormCommand, createSingleServer, killallServers, PeerTubeServer } from '@shared/server-commands'
|
import {
|
||||||
|
cleanupTests,
|
||||||
|
ConfigCommand,
|
||||||
|
ContactFormCommand,
|
||||||
|
createSingleServer,
|
||||||
|
killallServers,
|
||||||
|
PeerTubeServer
|
||||||
|
} from '@shared/server-commands'
|
||||||
|
|
||||||
describe('Test contact form API validators', function () {
|
describe('Test contact form API validators', function () {
|
||||||
let server: PeerTubeServer
|
let server: PeerTubeServer
|
||||||
|
@ -38,7 +45,7 @@ describe('Test contact form API validators', function () {
|
||||||
await killallServers([ server ])
|
await killallServers([ server ])
|
||||||
|
|
||||||
// Contact form is disabled
|
// Contact form is disabled
|
||||||
await server.run({ smtp: { hostname: '127.0.0.1', port: emailPort }, contact_form: { enabled: false } })
|
await server.run({ ...ConfigCommand.getEmailOverrideConfig(emailPort), contact_form: { enabled: false } })
|
||||||
await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 })
|
await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -48,7 +55,7 @@ describe('Test contact form API validators', function () {
|
||||||
await killallServers([ server ])
|
await killallServers([ server ])
|
||||||
|
|
||||||
// Email & contact form enabled
|
// Email & contact form enabled
|
||||||
await server.run({ smtp: { hostname: '127.0.0.1', port: emailPort } })
|
await server.run(ConfigCommand.getEmailOverrideConfig(emailPort))
|
||||||
|
|
||||||
await command.send({ ...defaultBody, fromEmail: 'badEmail', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
await command.send({ ...defaultBody, fromEmail: 'badEmail', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
await command.send({ ...defaultBody, fromEmail: 'badEmail@', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
await command.send({ ...defaultBody, fromEmail: 'badEmail@', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
|
|
|
@ -15,6 +15,7 @@ import './metrics'
|
||||||
import './my-user'
|
import './my-user'
|
||||||
import './plugins'
|
import './plugins'
|
||||||
import './redundancy'
|
import './redundancy'
|
||||||
|
import './registrations'
|
||||||
import './search'
|
import './search'
|
||||||
import './services'
|
import './services'
|
||||||
import './transcoding'
|
import './transcoding'
|
||||||
|
@ -23,7 +24,7 @@ import './upload-quota'
|
||||||
import './user-notifications'
|
import './user-notifications'
|
||||||
import './user-subscriptions'
|
import './user-subscriptions'
|
||||||
import './users-admin'
|
import './users-admin'
|
||||||
import './users'
|
import './users-emails'
|
||||||
import './video-blacklist'
|
import './video-blacklist'
|
||||||
import './video-captions'
|
import './video-captions'
|
||||||
import './video-channel-syncs'
|
import './video-channel-syncs'
|
||||||
|
|
402
server/tests/api/check-params/registrations.ts
Normal file
402
server/tests/api/check-params/registrations.ts
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
|
||||||
|
import { omit } from '@shared/core-utils'
|
||||||
|
import { HttpStatusCode, UserRole } from '@shared/models'
|
||||||
|
import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
|
||||||
|
|
||||||
|
describe('Test registrations API validators', function () {
|
||||||
|
let server: PeerTubeServer
|
||||||
|
let userToken: string
|
||||||
|
let moderatorToken: string
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(30000)
|
||||||
|
|
||||||
|
server = await createSingleServer(1)
|
||||||
|
|
||||||
|
await setAccessTokensToServers([ server ])
|
||||||
|
await server.config.enableSignup(false);
|
||||||
|
|
||||||
|
({ token: moderatorToken } = await server.users.generate('moderator', UserRole.MODERATOR));
|
||||||
|
({ token: userToken } = await server.users.generate('user', UserRole.USER))
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Register', function () {
|
||||||
|
const registrationPath = '/api/v1/users/register'
|
||||||
|
const registrationRequestPath = '/api/v1/users/registrations/request'
|
||||||
|
|
||||||
|
const baseCorrectParams = {
|
||||||
|
username: 'user3',
|
||||||
|
displayName: 'super user',
|
||||||
|
email: 'test3@example.com',
|
||||||
|
password: 'my super password',
|
||||||
|
registrationReason: 'my super registration reason'
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('When registering a new user or requesting user registration', function () {
|
||||||
|
|
||||||
|
async function check (fields: any, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
|
||||||
|
await makePostBodyRequest({ url: server.url, path: registrationPath, fields, expectedStatus })
|
||||||
|
await makePostBodyRequest({ url: server.url, path: registrationRequestPath, fields, expectedStatus })
|
||||||
|
}
|
||||||
|
|
||||||
|
it('Should fail with a too small username', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, username: '' }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a too long username', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, username: 'super'.repeat(50) }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an incorrect username', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, username: 'my username' }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a missing email', async function () {
|
||||||
|
const fields = omit(baseCorrectParams, [ 'email' ])
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an invalid email', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, email: 'test_example.com' }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a too small password', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, password: 'bla' }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a too long password', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, password: 'super'.repeat(61) }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail if we register a user with the same username', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, username: 'root' }
|
||||||
|
|
||||||
|
await check(fields, HttpStatusCode.CONFLICT_409)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a "peertube" username', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, username: 'peertube' }
|
||||||
|
|
||||||
|
await check(fields, HttpStatusCode.CONFLICT_409)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail if we register a user with the same email', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, email: 'admin' + server.internalServerNumber + '@example.com' }
|
||||||
|
|
||||||
|
await check(fields, HttpStatusCode.CONFLICT_409)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a bad display name', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, displayName: 'a'.repeat(150) }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a bad channel name', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, channel: { name: '[]azf', displayName: 'toto' } }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a bad channel display name', async function () {
|
||||||
|
const fields = { ...baseCorrectParams, channel: { name: 'toto', displayName: '' } }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a channel name that is the same as username', async function () {
|
||||||
|
const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } }
|
||||||
|
const fields = { ...baseCorrectParams, ...source }
|
||||||
|
|
||||||
|
await check(fields)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an existing channel', async function () {
|
||||||
|
const attributes = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
|
||||||
|
await server.channels.create({ attributes })
|
||||||
|
|
||||||
|
const fields = { ...baseCorrectParams, channel: { name: 'existing_channel', displayName: 'toto' } }
|
||||||
|
|
||||||
|
await check(fields, HttpStatusCode.CONFLICT_409)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail on a server with registration disabled', async function () {
|
||||||
|
this.timeout(60000)
|
||||||
|
|
||||||
|
await server.config.updateCustomSubConfig({
|
||||||
|
newConfig: {
|
||||||
|
signup: {
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await server.registrations.register({ username: 'user4', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
|
await server.registrations.requestRegistration({
|
||||||
|
username: 'user4',
|
||||||
|
registrationReason: 'reason',
|
||||||
|
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail if the user limit is reached', async function () {
|
||||||
|
this.timeout(60000)
|
||||||
|
|
||||||
|
const { total } = await server.users.list()
|
||||||
|
|
||||||
|
await server.config.updateCustomSubConfig({ newConfig: { signup: { limit: total } } })
|
||||||
|
|
||||||
|
await server.registrations.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
|
await server.registrations.requestRegistration({
|
||||||
|
username: 'user42',
|
||||||
|
registrationReason: 'reason',
|
||||||
|
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('On direct registration', function () {
|
||||||
|
|
||||||
|
it('Should succeed with the correct params', async function () {
|
||||||
|
await server.config.enableSignup(false)
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
username: 'user_direct_1',
|
||||||
|
displayName: 'super user direct 1',
|
||||||
|
email: 'user_direct_1@example.com',
|
||||||
|
password: 'my super password',
|
||||||
|
channel: { name: 'super_user_direct_1_channel', displayName: 'super user direct 1 channel' }
|
||||||
|
}
|
||||||
|
|
||||||
|
await makePostBodyRequest({ url: server.url, path: registrationPath, fields, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail if the instance requires approval', async function () {
|
||||||
|
this.timeout(60000)
|
||||||
|
|
||||||
|
await server.config.enableSignup(true)
|
||||||
|
await server.registrations.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('On registration request', function () {
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(60000)
|
||||||
|
|
||||||
|
await server.config.enableSignup(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an invalid registration reason', async function () {
|
||||||
|
for (const registrationReason of [ '', 't', 't'.repeat(5000) ]) {
|
||||||
|
await server.registrations.requestRegistration({
|
||||||
|
username: 'user_request_1',
|
||||||
|
registrationReason,
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should succeed with the correct params', async function () {
|
||||||
|
await server.registrations.requestRegistration({
|
||||||
|
username: 'user_request_2',
|
||||||
|
registrationReason: 'tt',
|
||||||
|
channel: {
|
||||||
|
displayName: 'my user request 2 channel',
|
||||||
|
name: 'user_request_2_channel'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail if the user is already awaiting registration approval', async function () {
|
||||||
|
await server.registrations.requestRegistration({
|
||||||
|
username: 'user_request_2',
|
||||||
|
registrationReason: 'tt',
|
||||||
|
channel: {
|
||||||
|
displayName: 'my user request 42 channel',
|
||||||
|
name: 'user_request_42_channel'
|
||||||
|
},
|
||||||
|
expectedStatus: HttpStatusCode.CONFLICT_409
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail if the channel is already awaiting registration approval', async function () {
|
||||||
|
await server.registrations.requestRegistration({
|
||||||
|
username: 'user42',
|
||||||
|
registrationReason: 'tt',
|
||||||
|
channel: {
|
||||||
|
displayName: 'my user request 2 channel',
|
||||||
|
name: 'user_request_2_channel'
|
||||||
|
},
|
||||||
|
expectedStatus: HttpStatusCode.CONFLICT_409
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail if the instance does not require approval', async function () {
|
||||||
|
this.timeout(60000)
|
||||||
|
|
||||||
|
await server.config.enableSignup(false)
|
||||||
|
|
||||||
|
await server.registrations.requestRegistration({
|
||||||
|
username: 'user42',
|
||||||
|
registrationReason: 'toto',
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Registrations accept/reject', function () {
|
||||||
|
let id1: number
|
||||||
|
let id2: number
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(60000)
|
||||||
|
|
||||||
|
await server.config.enableSignup(true);
|
||||||
|
|
||||||
|
({ id: id1 } = await server.registrations.requestRegistration({ username: 'request_2', registrationReason: 'toto' }));
|
||||||
|
({ id: id2 } = await server.registrations.requestRegistration({ username: 'request_3', registrationReason: 'toto' }))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail to accept/reject registration without token', async function () {
|
||||||
|
const options = { id: id1, moderationResponse: 'tt', token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }
|
||||||
|
await server.registrations.accept(options)
|
||||||
|
await server.registrations.reject(options)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail to accept/reject registration with a non moderator user', async function () {
|
||||||
|
const options = { id: id1, moderationResponse: 'tt', token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
|
||||||
|
await server.registrations.accept(options)
|
||||||
|
await server.registrations.reject(options)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail to accept/reject registration with a bad registration id', async function () {
|
||||||
|
{
|
||||||
|
const options = { id: 't' as any, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
|
||||||
|
await server.registrations.accept(options)
|
||||||
|
await server.registrations.reject(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const options = { id: 42, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
|
||||||
|
await server.registrations.accept(options)
|
||||||
|
await server.registrations.reject(options)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail to accept/reject registration with a bad moderation resposne', async function () {
|
||||||
|
for (const moderationResponse of [ '', 't', 't'.repeat(5000) ]) {
|
||||||
|
const options = { id: id1, moderationResponse, token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
|
||||||
|
await server.registrations.accept(options)
|
||||||
|
await server.registrations.reject(options)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should succeed to accept a registration', async function () {
|
||||||
|
await server.registrations.accept({ id: id1, moderationResponse: 'tt', token: moderatorToken })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should succeed to reject a registration', async function () {
|
||||||
|
await server.registrations.reject({ id: id2, moderationResponse: 'tt', token: moderatorToken })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail to accept/reject a registration that was already accepted/rejected', async function () {
|
||||||
|
for (const id of [ id1, id2 ]) {
|
||||||
|
const options = { id, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.CONFLICT_409 }
|
||||||
|
await server.registrations.accept(options)
|
||||||
|
await server.registrations.reject(options)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Registrations deletion', function () {
|
||||||
|
let id1: number
|
||||||
|
let id2: number
|
||||||
|
let id3: number
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
({ id: id1 } = await server.registrations.requestRegistration({ username: 'request_4', registrationReason: 'toto' }));
|
||||||
|
({ id: id2 } = await server.registrations.requestRegistration({ username: 'request_5', registrationReason: 'toto' }));
|
||||||
|
({ id: id3 } = await server.registrations.requestRegistration({ username: 'request_6', registrationReason: 'toto' }))
|
||||||
|
|
||||||
|
await server.registrations.accept({ id: id2, moderationResponse: 'tt' })
|
||||||
|
await server.registrations.reject({ id: id3, moderationResponse: 'tt' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail to delete registration without token', async function () {
|
||||||
|
await server.registrations.delete({ id: id1, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail to delete registration with a non moderator user', async function () {
|
||||||
|
await server.registrations.delete({ id: id1, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail to delete registration with a bad registration id', async function () {
|
||||||
|
await server.registrations.delete({ id: 't' as any, token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
|
await server.registrations.delete({ id: 42, token: moderatorToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should succeed with the correct params', async function () {
|
||||||
|
await server.registrations.delete({ id: id1, token: moderatorToken })
|
||||||
|
await server.registrations.delete({ id: id2, token: moderatorToken })
|
||||||
|
await server.registrations.delete({ id: id3, token: moderatorToken })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Listing registrations', function () {
|
||||||
|
const path = '/api/v1/users/registrations'
|
||||||
|
|
||||||
|
it('Should fail with a bad start pagination', async function () {
|
||||||
|
await checkBadStartPagination(server.url, path, server.accessToken)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a bad count pagination', async function () {
|
||||||
|
await checkBadCountPagination(server.url, path, server.accessToken)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an incorrect sort', async function () {
|
||||||
|
await checkBadSortPagination(server.url, path, server.accessToken)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a non authenticated user', async function () {
|
||||||
|
await server.registrations.list({
|
||||||
|
token: null,
|
||||||
|
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a non admin user', async function () {
|
||||||
|
await server.registrations.list({
|
||||||
|
token: userToken,
|
||||||
|
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should succeed with the correct params', async function () {
|
||||||
|
await server.registrations.list({
|
||||||
|
token: moderatorToken,
|
||||||
|
search: 'toto'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(async function () {
|
||||||
|
await cleanupTests([ server ])
|
||||||
|
})
|
||||||
|
})
|
|
@ -42,7 +42,7 @@ describe('Test upload quota', function () {
|
||||||
this.timeout(30000)
|
this.timeout(30000)
|
||||||
|
|
||||||
const user = { username: 'registered' + randomInt(1, 1500), password: 'password' }
|
const user = { username: 'registered' + randomInt(1, 1500), password: 'password' }
|
||||||
await server.users.register(user)
|
await server.registrations.register(user)
|
||||||
const userToken = await server.login.getAccessToken(user)
|
const userToken = await server.login.getAccessToken(user)
|
||||||
|
|
||||||
const attributes = { fixture: 'video_short2.webm' }
|
const attributes = { fixture: 'video_short2.webm' }
|
||||||
|
@ -57,7 +57,7 @@ describe('Test upload quota', function () {
|
||||||
this.timeout(30000)
|
this.timeout(30000)
|
||||||
|
|
||||||
const user = { username: 'registered' + randomInt(1, 1500), password: 'password' }
|
const user = { username: 'registered' + randomInt(1, 1500), password: 'password' }
|
||||||
await server.users.register(user)
|
await server.registrations.register(user)
|
||||||
const userToken = await server.login.getAccessToken(user)
|
const userToken = await server.login.getAccessToken(user)
|
||||||
|
|
||||||
const attributes = { fixture: 'video_short2.webm' }
|
const attributes = { fixture: 'video_short2.webm' }
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { omit } from '@shared/core-utils'
|
||||||
import { HttpStatusCode, UserAdminFlag, UserRole } from '@shared/models'
|
import { HttpStatusCode, UserAdminFlag, UserRole } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
|
ConfigCommand,
|
||||||
createSingleServer,
|
createSingleServer,
|
||||||
killallServers,
|
killallServers,
|
||||||
makeGetRequest,
|
makeGetRequest,
|
||||||
|
@ -156,13 +157,7 @@ describe('Test users admin API validators', function () {
|
||||||
|
|
||||||
await killallServers([ server ])
|
await killallServers([ server ])
|
||||||
|
|
||||||
const config = {
|
await server.run(ConfigCommand.getEmailOverrideConfig(emailPort))
|
||||||
smtp: {
|
|
||||||
hostname: '127.0.0.1',
|
|
||||||
port: emailPort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await server.run(config)
|
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
...baseCorrectParams,
|
...baseCorrectParams,
|
||||||
|
|
119
server/tests/api/check-params/users-emails.ts
Normal file
119
server/tests/api/check-params/users-emails.ts
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||||
|
import { MockSmtpServer } from '@server/tests/shared'
|
||||||
|
import { HttpStatusCode, UserRole } from '@shared/models'
|
||||||
|
import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
|
||||||
|
|
||||||
|
describe('Test users API validators', function () {
|
||||||
|
let server: PeerTubeServer
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(30000)
|
||||||
|
|
||||||
|
server = await createSingleServer(1, {
|
||||||
|
rates_limit: {
|
||||||
|
ask_send_email: {
|
||||||
|
max: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await setAccessTokensToServers([ server ])
|
||||||
|
await server.config.enableSignup(true)
|
||||||
|
|
||||||
|
await server.users.generate('moderator2', UserRole.MODERATOR)
|
||||||
|
|
||||||
|
await server.registrations.requestRegistration({
|
||||||
|
username: 'request1',
|
||||||
|
registrationReason: 'tt'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('When asking a password reset', function () {
|
||||||
|
const path = '/api/v1/users/ask-reset-password'
|
||||||
|
|
||||||
|
it('Should fail with a missing email', async function () {
|
||||||
|
const fields = {}
|
||||||
|
|
||||||
|
await makePostBodyRequest({ url: server.url, path, fields })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an invalid email', async function () {
|
||||||
|
const fields = { email: 'hello' }
|
||||||
|
|
||||||
|
await makePostBodyRequest({ url: server.url, path, fields })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should success with the correct params', async function () {
|
||||||
|
const fields = { email: 'admin@example.com' }
|
||||||
|
|
||||||
|
await makePostBodyRequest({
|
||||||
|
url: server.url,
|
||||||
|
path,
|
||||||
|
fields,
|
||||||
|
expectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('When asking for an account verification email', function () {
|
||||||
|
const path = '/api/v1/users/ask-send-verify-email'
|
||||||
|
|
||||||
|
it('Should fail with a missing email', async function () {
|
||||||
|
const fields = {}
|
||||||
|
|
||||||
|
await makePostBodyRequest({ url: server.url, path, fields })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an invalid email', async function () {
|
||||||
|
const fields = { email: 'hello' }
|
||||||
|
|
||||||
|
await makePostBodyRequest({ url: server.url, path, fields })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should succeed with the correct params', async function () {
|
||||||
|
const fields = { email: 'admin@example.com' }
|
||||||
|
|
||||||
|
await makePostBodyRequest({
|
||||||
|
url: server.url,
|
||||||
|
path,
|
||||||
|
fields,
|
||||||
|
expectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('When asking for a registration verification email', function () {
|
||||||
|
const path = '/api/v1/users/registrations/ask-send-verify-email'
|
||||||
|
|
||||||
|
it('Should fail with a missing email', async function () {
|
||||||
|
const fields = {}
|
||||||
|
|
||||||
|
await makePostBodyRequest({ url: server.url, path, fields })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an invalid email', async function () {
|
||||||
|
const fields = { email: 'hello' }
|
||||||
|
|
||||||
|
await makePostBodyRequest({ url: server.url, path, fields })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should succeed with the correct params', async function () {
|
||||||
|
const fields = { email: 'request1@example.com' }
|
||||||
|
|
||||||
|
await makePostBodyRequest({
|
||||||
|
url: server.url,
|
||||||
|
path,
|
||||||
|
fields,
|
||||||
|
expectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(async function () {
|
||||||
|
MockSmtpServer.Instance.kill()
|
||||||
|
|
||||||
|
await cleanupTests([ server ])
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,255 +0,0 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
|
||||||
import { MockSmtpServer } from '@server/tests/shared'
|
|
||||||
import { omit } from '@shared/core-utils'
|
|
||||||
import { HttpStatusCode, UserRole } from '@shared/models'
|
|
||||||
import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
|
|
||||||
|
|
||||||
describe('Test users API validators', function () {
|
|
||||||
const path = '/api/v1/users/'
|
|
||||||
let server: PeerTubeServer
|
|
||||||
let serverWithRegistrationDisabled: PeerTubeServer
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
before(async function () {
|
|
||||||
this.timeout(30000)
|
|
||||||
|
|
||||||
const res = await Promise.all([
|
|
||||||
createSingleServer(1, { signup: { limit: 3 } }),
|
|
||||||
createSingleServer(2)
|
|
||||||
])
|
|
||||||
|
|
||||||
server = res[0]
|
|
||||||
serverWithRegistrationDisabled = res[1]
|
|
||||||
|
|
||||||
await setAccessTokensToServers([ server ])
|
|
||||||
|
|
||||||
await server.users.generate('moderator2', UserRole.MODERATOR)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('When registering a new user', function () {
|
|
||||||
const registrationPath = path + '/register'
|
|
||||||
const baseCorrectParams = {
|
|
||||||
username: 'user3',
|
|
||||||
displayName: 'super user',
|
|
||||||
email: 'test3@example.com',
|
|
||||||
password: 'my super password'
|
|
||||||
}
|
|
||||||
|
|
||||||
it('Should fail with a too small username', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, username: '' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a too long username', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, username: 'super'.repeat(50) }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with an incorrect username', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, username: 'my username' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a missing email', async function () {
|
|
||||||
const fields = omit(baseCorrectParams, [ 'email' ])
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with an invalid email', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, email: 'test_example.com' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a too small password', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, password: 'bla' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a too long password', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, password: 'super'.repeat(61) }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail if we register a user with the same username', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, username: 'root' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({
|
|
||||||
url: server.url,
|
|
||||||
path: registrationPath,
|
|
||||||
token: server.accessToken,
|
|
||||||
fields,
|
|
||||||
expectedStatus: HttpStatusCode.CONFLICT_409
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a "peertube" username', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, username: 'peertube' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({
|
|
||||||
url: server.url,
|
|
||||||
path: registrationPath,
|
|
||||||
token: server.accessToken,
|
|
||||||
fields,
|
|
||||||
expectedStatus: HttpStatusCode.CONFLICT_409
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail if we register a user with the same email', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, email: 'admin' + server.internalServerNumber + '@example.com' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({
|
|
||||||
url: server.url,
|
|
||||||
path: registrationPath,
|
|
||||||
token: server.accessToken,
|
|
||||||
fields,
|
|
||||||
expectedStatus: HttpStatusCode.CONFLICT_409
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a bad display name', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, displayName: 'a'.repeat(150) }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a bad channel name', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, channel: { name: '[]azf', displayName: 'toto' } }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a bad channel display name', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, channel: { name: 'toto', displayName: '' } }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with a channel name that is the same as username', async function () {
|
|
||||||
const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } }
|
|
||||||
const fields = { ...baseCorrectParams, ...source }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with an existing channel', async function () {
|
|
||||||
const attributes = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
|
|
||||||
await server.channels.create({ attributes })
|
|
||||||
|
|
||||||
const fields = { ...baseCorrectParams, channel: { name: 'existing_channel', displayName: 'toto' } }
|
|
||||||
|
|
||||||
await makePostBodyRequest({
|
|
||||||
url: server.url,
|
|
||||||
path: registrationPath,
|
|
||||||
token: server.accessToken,
|
|
||||||
fields,
|
|
||||||
expectedStatus: HttpStatusCode.CONFLICT_409
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should succeed with the correct params', async function () {
|
|
||||||
const fields = { ...baseCorrectParams, channel: { name: 'super_channel', displayName: 'toto' } }
|
|
||||||
|
|
||||||
await makePostBodyRequest({
|
|
||||||
url: server.url,
|
|
||||||
path: registrationPath,
|
|
||||||
token: server.accessToken,
|
|
||||||
fields,
|
|
||||||
expectedStatus: HttpStatusCode.NO_CONTENT_204
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail on a server with registration disabled', async function () {
|
|
||||||
const fields = {
|
|
||||||
username: 'user4',
|
|
||||||
email: 'test4@example.com',
|
|
||||||
password: 'my super password 4'
|
|
||||||
}
|
|
||||||
|
|
||||||
await makePostBodyRequest({
|
|
||||||
url: serverWithRegistrationDisabled.url,
|
|
||||||
path: registrationPath,
|
|
||||||
token: serverWithRegistrationDisabled.accessToken,
|
|
||||||
fields,
|
|
||||||
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('When registering multiple users on a server with users limit', function () {
|
|
||||||
|
|
||||||
it('Should fail when after 3 registrations', async function () {
|
|
||||||
await server.users.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('When asking a password reset', function () {
|
|
||||||
const path = '/api/v1/users/ask-reset-password'
|
|
||||||
|
|
||||||
it('Should fail with a missing email', async function () {
|
|
||||||
const fields = {}
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with an invalid email', async function () {
|
|
||||||
const fields = { email: 'hello' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should success with the correct params', async function () {
|
|
||||||
const fields = { email: 'admin@example.com' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({
|
|
||||||
url: server.url,
|
|
||||||
path,
|
|
||||||
token: server.accessToken,
|
|
||||||
fields,
|
|
||||||
expectedStatus: HttpStatusCode.NO_CONTENT_204
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('When asking for an account verification email', function () {
|
|
||||||
const path = '/api/v1/users/ask-send-verify-email'
|
|
||||||
|
|
||||||
it('Should fail with a missing email', async function () {
|
|
||||||
const fields = {}
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should fail with an invalid email', async function () {
|
|
||||||
const fields = { email: 'hello' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should succeed with the correct params', async function () {
|
|
||||||
const fields = { email: 'admin@example.com' }
|
|
||||||
|
|
||||||
await makePostBodyRequest({
|
|
||||||
url: server.url,
|
|
||||||
path,
|
|
||||||
token: server.accessToken,
|
|
||||||
fields,
|
|
||||||
expectedStatus: HttpStatusCode.NO_CONTENT_204
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
after(async function () {
|
|
||||||
MockSmtpServer.Instance.kill()
|
|
||||||
|
|
||||||
await cleanupTests([ server, serverWithRegistrationDisabled ])
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -2,4 +2,5 @@ import './admin-notifications'
|
||||||
import './comments-notifications'
|
import './comments-notifications'
|
||||||
import './moderation-notifications'
|
import './moderation-notifications'
|
||||||
import './notifications-api'
|
import './notifications-api'
|
||||||
|
import './registrations-notifications'
|
||||||
import './user-notifications'
|
import './user-notifications'
|
||||||
|
|
|
@ -11,7 +11,6 @@ import {
|
||||||
checkNewInstanceFollower,
|
checkNewInstanceFollower,
|
||||||
checkNewVideoAbuseForModerators,
|
checkNewVideoAbuseForModerators,
|
||||||
checkNewVideoFromSubscription,
|
checkNewVideoFromSubscription,
|
||||||
checkUserRegistered,
|
|
||||||
checkVideoAutoBlacklistForModerators,
|
checkVideoAutoBlacklistForModerators,
|
||||||
checkVideoIsPublished,
|
checkVideoIsPublished,
|
||||||
MockInstancesIndex,
|
MockInstancesIndex,
|
||||||
|
@ -327,32 +326,6 @@ describe('Test moderation notifications', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('New registration', function () {
|
|
||||||
let baseParams: CheckerBaseParams
|
|
||||||
|
|
||||||
before(() => {
|
|
||||||
baseParams = {
|
|
||||||
server: servers[0],
|
|
||||||
emails,
|
|
||||||
socketNotifications: adminNotifications,
|
|
||||||
token: servers[0].accessToken
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should send a notification only to moderators when a user registers on the instance', async function () {
|
|
||||||
this.timeout(10000)
|
|
||||||
|
|
||||||
await servers[0].users.register({ username: 'user_45' })
|
|
||||||
|
|
||||||
await waitJobs(servers)
|
|
||||||
|
|
||||||
await checkUserRegistered({ ...baseParams, username: 'user_45', checkType: 'presence' })
|
|
||||||
|
|
||||||
const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } }
|
|
||||||
await checkUserRegistered({ ...baseParams, ...userOverride, username: 'user_45', checkType: 'absence' })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('New instance follows', function () {
|
describe('New instance follows', function () {
|
||||||
const instanceIndexServer = new MockInstancesIndex()
|
const instanceIndexServer = new MockInstancesIndex()
|
||||||
let config: any
|
let config: any
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||||
|
|
||||||
|
import {
|
||||||
|
CheckerBaseParams,
|
||||||
|
checkRegistrationRequest,
|
||||||
|
checkUserRegistered,
|
||||||
|
MockSmtpServer,
|
||||||
|
prepareNotificationsTest
|
||||||
|
} from '@server/tests/shared'
|
||||||
|
import { UserNotification } from '@shared/models'
|
||||||
|
import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands'
|
||||||
|
|
||||||
|
describe('Test registrations notifications', function () {
|
||||||
|
let server: PeerTubeServer
|
||||||
|
let userToken1: string
|
||||||
|
|
||||||
|
let userNotifications: UserNotification[] = []
|
||||||
|
let adminNotifications: UserNotification[] = []
|
||||||
|
let emails: object[] = []
|
||||||
|
|
||||||
|
let baseParams: CheckerBaseParams
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(50000)
|
||||||
|
|
||||||
|
const res = await prepareNotificationsTest(1)
|
||||||
|
|
||||||
|
server = res.servers[0]
|
||||||
|
emails = res.emails
|
||||||
|
userToken1 = res.userAccessToken
|
||||||
|
adminNotifications = res.adminNotifications
|
||||||
|
userNotifications = res.userNotifications
|
||||||
|
|
||||||
|
baseParams = {
|
||||||
|
server,
|
||||||
|
emails,
|
||||||
|
socketNotifications: adminNotifications,
|
||||||
|
token: server.accessToken
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('New direct registration for moderators', function () {
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
await server.config.enableSignup(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should send a notification only to moderators when a user registers on the instance', async function () {
|
||||||
|
this.timeout(50000)
|
||||||
|
|
||||||
|
await server.registrations.register({ username: 'user_10' })
|
||||||
|
|
||||||
|
await waitJobs([ server ])
|
||||||
|
|
||||||
|
await checkUserRegistered({ ...baseParams, username: 'user_10', checkType: 'presence' })
|
||||||
|
|
||||||
|
const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } }
|
||||||
|
await checkUserRegistered({ ...baseParams, ...userOverride, username: 'user_10', checkType: 'absence' })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('New registration request for moderators', function () {
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
await server.config.enableSignup(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should send a notification on new registration request', async function () {
|
||||||
|
this.timeout(50000)
|
||||||
|
|
||||||
|
const registrationReason = 'my reason'
|
||||||
|
await server.registrations.requestRegistration({ username: 'user_11', registrationReason })
|
||||||
|
|
||||||
|
await waitJobs([ server ])
|
||||||
|
|
||||||
|
await checkRegistrationRequest({ ...baseParams, username: 'user_11', registrationReason, checkType: 'presence' })
|
||||||
|
|
||||||
|
const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } }
|
||||||
|
await checkRegistrationRequest({ ...baseParams, ...userOverride, username: 'user_11', registrationReason, checkType: 'absence' })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(async function () {
|
||||||
|
MockSmtpServer.Instance.kill()
|
||||||
|
|
||||||
|
await cleanupTests([ server ])
|
||||||
|
})
|
||||||
|
})
|
|
@ -149,7 +149,7 @@ describe('Test config defaults', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should register a user with this default setting', async function () {
|
it('Should register a user with this default setting', async function () {
|
||||||
await server.users.register({ username: 'user_p2p_2' })
|
await server.registrations.register({ username: 'user_p2p_2' })
|
||||||
|
|
||||||
const userToken = await server.login.getAccessToken('user_p2p_2')
|
const userToken = await server.login.getAccessToken('user_p2p_2')
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ describe('Test config defaults', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should register a user with this default setting', async function () {
|
it('Should register a user with this default setting', async function () {
|
||||||
await server.users.register({ username: 'user_p2p_4' })
|
await server.registrations.register({ username: 'user_p2p_4' })
|
||||||
|
|
||||||
const userToken = await server.login.getAccessToken('user_p2p_4')
|
const userToken = await server.login.getAccessToken('user_p2p_4')
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
|
||||||
expect(data.signup.enabled).to.be.true
|
expect(data.signup.enabled).to.be.true
|
||||||
expect(data.signup.limit).to.equal(4)
|
expect(data.signup.limit).to.equal(4)
|
||||||
expect(data.signup.minimumAge).to.equal(16)
|
expect(data.signup.minimumAge).to.equal(16)
|
||||||
|
expect(data.signup.requiresApproval).to.be.false
|
||||||
expect(data.signup.requiresEmailVerification).to.be.false
|
expect(data.signup.requiresEmailVerification).to.be.false
|
||||||
|
|
||||||
expect(data.admin.email).to.equal('admin' + server.internalServerNumber + '@example.com')
|
expect(data.admin.email).to.equal('admin' + server.internalServerNumber + '@example.com')
|
||||||
|
@ -152,6 +153,7 @@ function checkUpdatedConfig (data: CustomConfig) {
|
||||||
|
|
||||||
expect(data.signup.enabled).to.be.false
|
expect(data.signup.enabled).to.be.false
|
||||||
expect(data.signup.limit).to.equal(5)
|
expect(data.signup.limit).to.equal(5)
|
||||||
|
expect(data.signup.requiresApproval).to.be.false
|
||||||
expect(data.signup.requiresEmailVerification).to.be.false
|
expect(data.signup.requiresEmailVerification).to.be.false
|
||||||
expect(data.signup.minimumAge).to.equal(10)
|
expect(data.signup.minimumAge).to.equal(10)
|
||||||
|
|
||||||
|
@ -285,6 +287,7 @@ const newCustomConfig: CustomConfig = {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
limit: 5,
|
limit: 5,
|
||||||
|
requiresApproval: false,
|
||||||
requiresEmailVerification: false,
|
requiresEmailVerification: false,
|
||||||
minimumAge: 10
|
minimumAge: 10
|
||||||
},
|
},
|
||||||
|
@ -468,9 +471,9 @@ describe('Test config', function () {
|
||||||
this.timeout(5000)
|
this.timeout(5000)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
server.users.register({ username: 'user1' }),
|
server.registrations.register({ username: 'user1' }),
|
||||||
server.users.register({ username: 'user2' }),
|
server.registrations.register({ username: 'user2' }),
|
||||||
server.users.register({ username: 'user3' })
|
server.registrations.register({ username: 'user3' })
|
||||||
])
|
])
|
||||||
|
|
||||||
const data = await server.config.getConfig()
|
const data = await server.config.getConfig()
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { wait } from '@shared/core-utils'
|
||||||
import { HttpStatusCode } from '@shared/models'
|
import { HttpStatusCode } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
|
ConfigCommand,
|
||||||
ContactFormCommand,
|
ContactFormCommand,
|
||||||
createSingleServer,
|
createSingleServer,
|
||||||
PeerTubeServer,
|
PeerTubeServer,
|
||||||
|
@ -23,13 +24,7 @@ describe('Test contact form', function () {
|
||||||
|
|
||||||
const port = await MockSmtpServer.Instance.collectEmails(emails)
|
const port = await MockSmtpServer.Instance.collectEmails(emails)
|
||||||
|
|
||||||
const overrideConfig = {
|
server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(port))
|
||||||
smtp: {
|
|
||||||
hostname: '127.0.0.1',
|
|
||||||
port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
server = await createSingleServer(1, overrideConfig)
|
|
||||||
await setAccessTokensToServers([ server ])
|
await setAccessTokensToServers([ server ])
|
||||||
|
|
||||||
command = server.contactForm
|
command = server.contactForm
|
||||||
|
|
|
@ -3,7 +3,14 @@
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { MockSmtpServer } from '@server/tests/shared'
|
import { MockSmtpServer } from '@server/tests/shared'
|
||||||
import { HttpStatusCode } from '@shared/models'
|
import { HttpStatusCode } from '@shared/models'
|
||||||
import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/server-commands'
|
import {
|
||||||
|
cleanupTests,
|
||||||
|
ConfigCommand,
|
||||||
|
createSingleServer,
|
||||||
|
PeerTubeServer,
|
||||||
|
setAccessTokensToServers,
|
||||||
|
waitJobs
|
||||||
|
} from '@shared/server-commands'
|
||||||
|
|
||||||
describe('Test emails', function () {
|
describe('Test emails', function () {
|
||||||
let server: PeerTubeServer
|
let server: PeerTubeServer
|
||||||
|
@ -24,21 +31,15 @@ describe('Test emails', function () {
|
||||||
username: 'user_1',
|
username: 'user_1',
|
||||||
password: 'super_password'
|
password: 'super_password'
|
||||||
}
|
}
|
||||||
let emailPort: number
|
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
this.timeout(50000)
|
this.timeout(50000)
|
||||||
|
|
||||||
emailPort = await MockSmtpServer.Instance.collectEmails(emails)
|
const emailPort = await MockSmtpServer.Instance.collectEmails(emails)
|
||||||
|
server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(emailPort))
|
||||||
|
|
||||||
const overrideConfig = {
|
|
||||||
smtp: {
|
|
||||||
hostname: '127.0.0.1',
|
|
||||||
port: emailPort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
server = await createSingleServer(1, overrideConfig)
|
|
||||||
await setAccessTokensToServers([ server ])
|
await setAccessTokensToServers([ server ])
|
||||||
|
await server.config.enableSignup(true)
|
||||||
|
|
||||||
{
|
{
|
||||||
const created = await server.users.create({ username: user.username, password: user.password })
|
const created = await server.users.create({ username: user.username, password: user.password })
|
||||||
|
@ -322,6 +323,62 @@ describe('Test emails', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('When verifying a registration email', function () {
|
||||||
|
let registrationId: number
|
||||||
|
let registrationIdEmail: number
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
const { id } = await server.registrations.requestRegistration({
|
||||||
|
username: 'request_1',
|
||||||
|
email: 'request_1@example.com',
|
||||||
|
registrationReason: 'tt'
|
||||||
|
})
|
||||||
|
registrationId = id
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should ask to send the verification email', async function () {
|
||||||
|
this.timeout(10000)
|
||||||
|
|
||||||
|
await server.registrations.askSendVerifyEmail({ email: 'request_1@example.com' })
|
||||||
|
|
||||||
|
await waitJobs(server)
|
||||||
|
expect(emails).to.have.lengthOf(9)
|
||||||
|
|
||||||
|
const email = emails[8]
|
||||||
|
|
||||||
|
expect(email['from'][0]['name']).equal('PeerTube')
|
||||||
|
expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
|
||||||
|
expect(email['to'][0]['address']).equal('request_1@example.com')
|
||||||
|
expect(email['subject']).contains('Verify')
|
||||||
|
|
||||||
|
const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text'])
|
||||||
|
expect(verificationStringMatches).not.to.be.null
|
||||||
|
|
||||||
|
verificationString = verificationStringMatches[1]
|
||||||
|
expect(verificationString).to.not.be.undefined
|
||||||
|
expect(verificationString).to.have.length.above(2)
|
||||||
|
|
||||||
|
const registrationIdMatches = /registrationId=([0-9]+)/.exec(email['text'])
|
||||||
|
expect(registrationIdMatches).not.to.be.null
|
||||||
|
|
||||||
|
registrationIdEmail = parseInt(registrationIdMatches[1], 10)
|
||||||
|
|
||||||
|
expect(registrationId).to.equal(registrationIdEmail)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should not verify the email with an invalid verification string', async function () {
|
||||||
|
await server.registrations.verifyEmail({
|
||||||
|
registrationId: registrationIdEmail,
|
||||||
|
verificationString: verificationString + 'b',
|
||||||
|
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should verify the email', async function () {
|
||||||
|
await server.registrations.verifyEmail({ registrationId: registrationIdEmail, verificationString })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
MockSmtpServer.Instance.kill()
|
MockSmtpServer.Instance.kill()
|
||||||
|
|
||||||
|
|
|
@ -106,13 +106,13 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
it('Should rate limit signup', async function () {
|
it('Should rate limit signup', async function () {
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
try {
|
try {
|
||||||
await server.users.register({ username: 'test' + i })
|
await server.registrations.register({ username: 'test' + i })
|
||||||
} catch {
|
} catch {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await server.users.register({ username: 'test42', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
|
await server.registrations.register({ username: 'test42', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not rate limit failed signup', async function () {
|
it('Should not rate limit failed signup', async function () {
|
||||||
|
@ -121,10 +121,10 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
await wait(7000)
|
await wait(7000)
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
await server.users.register({ username: 'test' + i, expectedStatus: HttpStatusCode.CONFLICT_409 })
|
await server.registrations.register({ username: 'test' + i, expectedStatus: HttpStatusCode.CONFLICT_409 })
|
||||||
}
|
}
|
||||||
|
|
||||||
await server.users.register({ username: 'test43', expectedStatus: HttpStatusCode.NO_CONTENT_204 })
|
await server.registrations.register({ username: 'test43', expectedStatus: HttpStatusCode.NO_CONTENT_204 })
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import './oauth'
|
import './oauth'
|
||||||
|
import './registrations`'
|
||||||
import './two-factor'
|
import './two-factor'
|
||||||
import './user-subscriptions'
|
import './user-subscriptions'
|
||||||
import './user-videos'
|
import './user-videos'
|
||||||
import './users'
|
import './users'
|
||||||
import './users-multiple-servers'
|
import './users-multiple-servers'
|
||||||
import './users-verification'
|
import './users-email-verification'
|
||||||
|
|
379
server/tests/api/users/registrations.ts
Normal file
379
server/tests/api/users/registrations.ts
Normal file
|
@ -0,0 +1,379 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||||
|
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { MockSmtpServer } from '@server/tests/shared'
|
||||||
|
import { UserRegistrationState, UserRole } from '@shared/models'
|
||||||
|
import {
|
||||||
|
cleanupTests,
|
||||||
|
ConfigCommand,
|
||||||
|
createSingleServer,
|
||||||
|
PeerTubeServer,
|
||||||
|
setAccessTokensToServers,
|
||||||
|
waitJobs
|
||||||
|
} from '@shared/server-commands'
|
||||||
|
|
||||||
|
describe('Test registrations', function () {
|
||||||
|
let server: PeerTubeServer
|
||||||
|
|
||||||
|
const emails: object[] = []
|
||||||
|
let emailPort: number
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(30000)
|
||||||
|
|
||||||
|
emailPort = await MockSmtpServer.Instance.collectEmails(emails)
|
||||||
|
|
||||||
|
server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(emailPort))
|
||||||
|
|
||||||
|
await setAccessTokensToServers([ server ])
|
||||||
|
await server.config.enableSignup(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Direct registrations of a new user', function () {
|
||||||
|
let user1Token: string
|
||||||
|
|
||||||
|
it('Should register a new user', async function () {
|
||||||
|
const user = { displayName: 'super user 1', username: 'user_1', password: 'my super password' }
|
||||||
|
const channel = { name: 'my_user_1_channel', displayName: 'my channel rocks' }
|
||||||
|
|
||||||
|
await server.registrations.register({ ...user, channel })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should be able to login with this registered user', async function () {
|
||||||
|
const user1 = { username: 'user_1', password: 'my super password' }
|
||||||
|
|
||||||
|
user1Token = await server.login.getAccessToken(user1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should have the correct display name', async function () {
|
||||||
|
const user = await server.users.getMyInfo({ token: user1Token })
|
||||||
|
expect(user.account.displayName).to.equal('super user 1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should have the correct video quota', async function () {
|
||||||
|
const user = await server.users.getMyInfo({ token: user1Token })
|
||||||
|
expect(user.videoQuota).to.equal(5 * 1024 * 1024)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should have created the channel', async function () {
|
||||||
|
const { displayName } = await server.channels.get({ channelName: 'my_user_1_channel' })
|
||||||
|
|
||||||
|
expect(displayName).to.equal('my channel rocks')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should remove me', async function () {
|
||||||
|
{
|
||||||
|
const { data } = await server.users.list()
|
||||||
|
expect(data.find(u => u.username === 'user_1')).to.not.be.undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
await server.users.deleteMe({ token: user1Token })
|
||||||
|
|
||||||
|
{
|
||||||
|
const { data } = await server.users.list()
|
||||||
|
expect(data.find(u => u.username === 'user_1')).to.be.undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Registration requests', function () {
|
||||||
|
let id2: number
|
||||||
|
let id3: number
|
||||||
|
let id4: number
|
||||||
|
|
||||||
|
let user2Token: string
|
||||||
|
let user3Token: string
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(60000)
|
||||||
|
|
||||||
|
await server.config.enableSignup(true)
|
||||||
|
|
||||||
|
{
|
||||||
|
const { id } = await server.registrations.requestRegistration({
|
||||||
|
username: 'user4',
|
||||||
|
registrationReason: 'registration reason 4'
|
||||||
|
})
|
||||||
|
|
||||||
|
id4 = id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should request a registration without a channel', async function () {
|
||||||
|
{
|
||||||
|
const { id } = await server.registrations.requestRegistration({
|
||||||
|
username: 'user2',
|
||||||
|
displayName: 'my super user 2',
|
||||||
|
email: 'user2@example.com',
|
||||||
|
password: 'user2password',
|
||||||
|
registrationReason: 'registration reason 2'
|
||||||
|
})
|
||||||
|
|
||||||
|
id2 = id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should request a registration with a channel', async function () {
|
||||||
|
const { id } = await server.registrations.requestRegistration({
|
||||||
|
username: 'user3',
|
||||||
|
displayName: 'my super user 3',
|
||||||
|
channel: {
|
||||||
|
displayName: 'my user 3 channel',
|
||||||
|
name: 'super_user3_channel'
|
||||||
|
},
|
||||||
|
email: 'user3@example.com',
|
||||||
|
password: 'user3password',
|
||||||
|
registrationReason: 'registration reason 3'
|
||||||
|
})
|
||||||
|
|
||||||
|
id3 = id
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should list these registration requests', async function () {
|
||||||
|
{
|
||||||
|
const { total, data } = await server.registrations.list({ sort: '-createdAt' })
|
||||||
|
expect(total).to.equal(3)
|
||||||
|
expect(data).to.have.lengthOf(3)
|
||||||
|
|
||||||
|
{
|
||||||
|
expect(data[0].id).to.equal(id3)
|
||||||
|
expect(data[0].username).to.equal('user3')
|
||||||
|
expect(data[0].accountDisplayName).to.equal('my super user 3')
|
||||||
|
|
||||||
|
expect(data[0].channelDisplayName).to.equal('my user 3 channel')
|
||||||
|
expect(data[0].channelHandle).to.equal('super_user3_channel')
|
||||||
|
|
||||||
|
expect(data[0].createdAt).to.exist
|
||||||
|
expect(data[0].updatedAt).to.exist
|
||||||
|
|
||||||
|
expect(data[0].email).to.equal('user3@example.com')
|
||||||
|
expect(data[0].emailVerified).to.be.null
|
||||||
|
|
||||||
|
expect(data[0].moderationResponse).to.be.null
|
||||||
|
expect(data[0].registrationReason).to.equal('registration reason 3')
|
||||||
|
expect(data[0].state.id).to.equal(UserRegistrationState.PENDING)
|
||||||
|
expect(data[0].state.label).to.equal('Pending')
|
||||||
|
expect(data[0].user).to.be.null
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expect(data[1].id).to.equal(id2)
|
||||||
|
expect(data[1].username).to.equal('user2')
|
||||||
|
expect(data[1].accountDisplayName).to.equal('my super user 2')
|
||||||
|
|
||||||
|
expect(data[1].channelDisplayName).to.be.null
|
||||||
|
expect(data[1].channelHandle).to.be.null
|
||||||
|
|
||||||
|
expect(data[1].createdAt).to.exist
|
||||||
|
expect(data[1].updatedAt).to.exist
|
||||||
|
|
||||||
|
expect(data[1].email).to.equal('user2@example.com')
|
||||||
|
expect(data[1].emailVerified).to.be.null
|
||||||
|
|
||||||
|
expect(data[1].moderationResponse).to.be.null
|
||||||
|
expect(data[1].registrationReason).to.equal('registration reason 2')
|
||||||
|
expect(data[1].state.id).to.equal(UserRegistrationState.PENDING)
|
||||||
|
expect(data[1].state.label).to.equal('Pending')
|
||||||
|
expect(data[1].user).to.be.null
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expect(data[2].username).to.equal('user4')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const { total, data } = await server.registrations.list({ count: 1, start: 1, sort: 'createdAt' })
|
||||||
|
|
||||||
|
expect(total).to.equal(3)
|
||||||
|
expect(data).to.have.lengthOf(1)
|
||||||
|
expect(data[0].id).to.equal(id2)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const { total, data } = await server.registrations.list({ search: 'user3' })
|
||||||
|
expect(total).to.equal(1)
|
||||||
|
expect(data).to.have.lengthOf(1)
|
||||||
|
expect(data[0].id).to.equal(id3)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should reject a registration request', async function () {
|
||||||
|
await server.registrations.reject({ id: id4, moderationResponse: 'I do not want id 4 on this instance' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should have sent an email to the user explanining the registration has been rejected', async function () {
|
||||||
|
this.timeout(50000)
|
||||||
|
|
||||||
|
await waitJobs([ server ])
|
||||||
|
|
||||||
|
const email = emails.find(e => e['to'][0]['address'] === 'user4@example.com')
|
||||||
|
expect(email).to.exist
|
||||||
|
|
||||||
|
expect(email['subject']).to.contain('been rejected')
|
||||||
|
expect(email['text']).to.contain('been rejected')
|
||||||
|
expect(email['text']).to.contain('I do not want id 4 on this instance')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should accept registration requests', async function () {
|
||||||
|
await server.registrations.accept({ id: id2, moderationResponse: 'Welcome id 2' })
|
||||||
|
await server.registrations.accept({ id: id3, moderationResponse: 'Welcome id 3' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should have sent an email to the user explanining the registration has been accepted', async function () {
|
||||||
|
this.timeout(50000)
|
||||||
|
|
||||||
|
await waitJobs([ server ])
|
||||||
|
|
||||||
|
{
|
||||||
|
const email = emails.find(e => e['to'][0]['address'] === 'user2@example.com')
|
||||||
|
expect(email).to.exist
|
||||||
|
|
||||||
|
expect(email['subject']).to.contain('been accepted')
|
||||||
|
expect(email['text']).to.contain('been accepted')
|
||||||
|
expect(email['text']).to.contain('Welcome id 2')
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const email = emails.find(e => e['to'][0]['address'] === 'user3@example.com')
|
||||||
|
expect(email).to.exist
|
||||||
|
|
||||||
|
expect(email['subject']).to.contain('been accepted')
|
||||||
|
expect(email['text']).to.contain('been accepted')
|
||||||
|
expect(email['text']).to.contain('Welcome id 3')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should login with these users', async function () {
|
||||||
|
user2Token = await server.login.getAccessToken({ username: 'user2', password: 'user2password' })
|
||||||
|
user3Token = await server.login.getAccessToken({ username: 'user3', password: 'user3password' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should have created the appropriate attributes for user 2', async function () {
|
||||||
|
const me = await server.users.getMyInfo({ token: user2Token })
|
||||||
|
|
||||||
|
expect(me.username).to.equal('user2')
|
||||||
|
expect(me.account.displayName).to.equal('my super user 2')
|
||||||
|
expect(me.videoQuota).to.equal(5 * 1024 * 1024)
|
||||||
|
expect(me.videoChannels[0].name).to.equal('user2_channel')
|
||||||
|
expect(me.videoChannels[0].displayName).to.equal('Main user2 channel')
|
||||||
|
expect(me.role.id).to.equal(UserRole.USER)
|
||||||
|
expect(me.email).to.equal('user2@example.com')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should have created the appropriate attributes for user 3', async function () {
|
||||||
|
const me = await server.users.getMyInfo({ token: user3Token })
|
||||||
|
|
||||||
|
expect(me.username).to.equal('user3')
|
||||||
|
expect(me.account.displayName).to.equal('my super user 3')
|
||||||
|
expect(me.videoQuota).to.equal(5 * 1024 * 1024)
|
||||||
|
expect(me.videoChannels[0].name).to.equal('super_user3_channel')
|
||||||
|
expect(me.videoChannels[0].displayName).to.equal('my user 3 channel')
|
||||||
|
expect(me.role.id).to.equal(UserRole.USER)
|
||||||
|
expect(me.email).to.equal('user3@example.com')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should list these accepted/rejected registration requests', async function () {
|
||||||
|
const { data } = await server.registrations.list({ sort: 'createdAt' })
|
||||||
|
const { data: users } = await server.users.list()
|
||||||
|
|
||||||
|
{
|
||||||
|
expect(data[0].id).to.equal(id4)
|
||||||
|
expect(data[0].state.id).to.equal(UserRegistrationState.REJECTED)
|
||||||
|
expect(data[0].state.label).to.equal('Rejected')
|
||||||
|
|
||||||
|
expect(data[0].moderationResponse).to.equal('I do not want id 4 on this instance')
|
||||||
|
expect(data[0].user).to.be.null
|
||||||
|
|
||||||
|
expect(users.find(u => u.username === 'user4')).to.not.exist
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expect(data[1].id).to.equal(id2)
|
||||||
|
expect(data[1].state.id).to.equal(UserRegistrationState.ACCEPTED)
|
||||||
|
expect(data[1].state.label).to.equal('Accepted')
|
||||||
|
|
||||||
|
expect(data[1].moderationResponse).to.equal('Welcome id 2')
|
||||||
|
expect(data[1].user).to.exist
|
||||||
|
|
||||||
|
const user2 = users.find(u => u.username === 'user2')
|
||||||
|
expect(data[1].user.id).to.equal(user2.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expect(data[2].id).to.equal(id3)
|
||||||
|
expect(data[2].state.id).to.equal(UserRegistrationState.ACCEPTED)
|
||||||
|
expect(data[2].state.label).to.equal('Accepted')
|
||||||
|
|
||||||
|
expect(data[2].moderationResponse).to.equal('Welcome id 3')
|
||||||
|
expect(data[2].user).to.exist
|
||||||
|
|
||||||
|
const user3 = users.find(u => u.username === 'user3')
|
||||||
|
expect(data[2].user.id).to.equal(user3.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Shoulde delete a registration', async function () {
|
||||||
|
await server.registrations.delete({ id: id2 })
|
||||||
|
await server.registrations.delete({ id: id3 })
|
||||||
|
|
||||||
|
const { total, data } = await server.registrations.list()
|
||||||
|
expect(total).to.equal(1)
|
||||||
|
expect(data).to.have.lengthOf(1)
|
||||||
|
expect(data[0].id).to.equal(id4)
|
||||||
|
|
||||||
|
const { data: users } = await server.users.list()
|
||||||
|
|
||||||
|
for (const username of [ 'user2', 'user3' ]) {
|
||||||
|
expect(users.find(u => u.username === username)).to.exist
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should request a registration without a channel, that will conflict with an already existing channel', async function () {
|
||||||
|
let id1: number
|
||||||
|
let id2: number
|
||||||
|
|
||||||
|
{
|
||||||
|
const { id } = await server.registrations.requestRegistration({
|
||||||
|
registrationReason: 'tt',
|
||||||
|
username: 'user5',
|
||||||
|
password: 'user5password',
|
||||||
|
channel: {
|
||||||
|
displayName: 'channel 6',
|
||||||
|
name: 'user6_channel'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
id1 = id
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const { id } = await server.registrations.requestRegistration({
|
||||||
|
registrationReason: 'tt',
|
||||||
|
username: 'user6',
|
||||||
|
password: 'user6password'
|
||||||
|
})
|
||||||
|
|
||||||
|
id2 = id
|
||||||
|
}
|
||||||
|
|
||||||
|
await server.registrations.accept({ id: id1, moderationResponse: 'tt' })
|
||||||
|
await server.registrations.accept({ id: id2, moderationResponse: 'tt' })
|
||||||
|
|
||||||
|
const user5Token = await server.login.getAccessToken('user5', 'user5password')
|
||||||
|
const user6Token = await server.login.getAccessToken('user6', 'user6password')
|
||||||
|
|
||||||
|
const user5 = await server.users.getMyInfo({ token: user5Token })
|
||||||
|
const user6 = await server.users.getMyInfo({ token: user6Token })
|
||||||
|
|
||||||
|
expect(user5.videoChannels[0].name).to.equal('user6_channel')
|
||||||
|
expect(user6.videoChannels[0].name).to.equal('user6_channel-1')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after(async function () {
|
||||||
|
MockSmtpServer.Instance.kill()
|
||||||
|
|
||||||
|
await cleanupTests([ server ])
|
||||||
|
})
|
||||||
|
})
|
|
@ -3,9 +3,16 @@
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { MockSmtpServer } from '@server/tests/shared'
|
import { MockSmtpServer } from '@server/tests/shared'
|
||||||
import { HttpStatusCode } from '@shared/models'
|
import { HttpStatusCode } from '@shared/models'
|
||||||
import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/server-commands'
|
import {
|
||||||
|
cleanupTests,
|
||||||
|
ConfigCommand,
|
||||||
|
createSingleServer,
|
||||||
|
PeerTubeServer,
|
||||||
|
setAccessTokensToServers,
|
||||||
|
waitJobs
|
||||||
|
} from '@shared/server-commands'
|
||||||
|
|
||||||
describe('Test users account verification', function () {
|
describe('Test users email verification', function () {
|
||||||
let server: PeerTubeServer
|
let server: PeerTubeServer
|
||||||
let userId: number
|
let userId: number
|
||||||
let userAccessToken: string
|
let userAccessToken: string
|
||||||
|
@ -25,14 +32,7 @@ describe('Test users account verification', function () {
|
||||||
this.timeout(30000)
|
this.timeout(30000)
|
||||||
|
|
||||||
const port = await MockSmtpServer.Instance.collectEmails(emails)
|
const port = await MockSmtpServer.Instance.collectEmails(emails)
|
||||||
|
server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(port))
|
||||||
const overrideConfig = {
|
|
||||||
smtp: {
|
|
||||||
hostname: '127.0.0.1',
|
|
||||||
port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
server = await createSingleServer(1, overrideConfig)
|
|
||||||
|
|
||||||
await setAccessTokensToServers([ server ])
|
await setAccessTokensToServers([ server ])
|
||||||
})
|
})
|
||||||
|
@ -40,17 +40,18 @@ describe('Test users account verification', function () {
|
||||||
it('Should register user and send verification email if verification required', async function () {
|
it('Should register user and send verification email if verification required', async function () {
|
||||||
this.timeout(30000)
|
this.timeout(30000)
|
||||||
|
|
||||||
await server.config.updateCustomSubConfig({
|
await server.config.updateExistingSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
requiresApproval: false,
|
||||||
requiresEmailVerification: true,
|
requiresEmailVerification: true,
|
||||||
limit: 10
|
limit: 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await server.users.register(user1)
|
await server.registrations.register(user1)
|
||||||
|
|
||||||
await waitJobs(server)
|
await waitJobs(server)
|
||||||
expectedEmailsLength++
|
expectedEmailsLength++
|
||||||
|
@ -127,17 +128,15 @@ describe('Test users account verification', function () {
|
||||||
|
|
||||||
it('Should register user not requiring email verification if setting not enabled', async function () {
|
it('Should register user not requiring email verification if setting not enabled', async function () {
|
||||||
this.timeout(5000)
|
this.timeout(5000)
|
||||||
await server.config.updateCustomSubConfig({
|
await server.config.updateExistingSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: true,
|
requiresEmailVerification: false
|
||||||
requiresEmailVerification: false,
|
|
||||||
limit: 10
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await server.users.register(user2)
|
await server.registrations.register(user2)
|
||||||
|
|
||||||
await waitJobs(server)
|
await waitJobs(server)
|
||||||
expect(emails).to.have.lengthOf(expectedEmailsLength)
|
expect(emails).to.have.lengthOf(expectedEmailsLength)
|
||||||
|
@ -152,9 +151,7 @@ describe('Test users account verification', function () {
|
||||||
await server.config.updateCustomSubConfig({
|
await server.config.updateCustomSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: true,
|
requiresEmailVerification: true
|
||||||
requiresEmailVerification: true,
|
|
||||||
limit: 10
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -429,56 +429,6 @@ describe('Test users', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Registering a new user', function () {
|
|
||||||
let user15AccessToken: string
|
|
||||||
|
|
||||||
it('Should register a new user', async function () {
|
|
||||||
const user = { displayName: 'super user 15', username: 'user_15', password: 'my super password' }
|
|
||||||
const channel = { name: 'my_user_15_channel', displayName: 'my channel rocks' }
|
|
||||||
|
|
||||||
await server.users.register({ ...user, channel })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should be able to login with this registered user', async function () {
|
|
||||||
const user15 = {
|
|
||||||
username: 'user_15',
|
|
||||||
password: 'my super password'
|
|
||||||
}
|
|
||||||
|
|
||||||
user15AccessToken = await server.login.getAccessToken(user15)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should have the correct display name', async function () {
|
|
||||||
const user = await server.users.getMyInfo({ token: user15AccessToken })
|
|
||||||
expect(user.account.displayName).to.equal('super user 15')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should have the correct video quota', async function () {
|
|
||||||
const user = await server.users.getMyInfo({ token: user15AccessToken })
|
|
||||||
expect(user.videoQuota).to.equal(5 * 1024 * 1024)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should have created the channel', async function () {
|
|
||||||
const { displayName } = await server.channels.get({ channelName: 'my_user_15_channel' })
|
|
||||||
|
|
||||||
expect(displayName).to.equal('my channel rocks')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should remove me', async function () {
|
|
||||||
{
|
|
||||||
const { data } = await server.users.list()
|
|
||||||
expect(data.find(u => u.username === 'user_15')).to.not.be.undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
await server.users.deleteMe({ token: user15AccessToken })
|
|
||||||
|
|
||||||
{
|
|
||||||
const { data } = await server.users.list()
|
|
||||||
expect(data.find(u => u.username === 'user_15')).to.be.undefined
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('User blocking', function () {
|
describe('User blocking', function () {
|
||||||
let user16Id: number
|
let user16Id: number
|
||||||
let user16AccessToken: string
|
let user16AccessToken: string
|
||||||
|
|
|
@ -138,14 +138,14 @@ describe('Official plugin Akismet', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should allow signup', async function () {
|
it('Should allow signup', async function () {
|
||||||
await servers[0].users.register({
|
await servers[0].registrations.register({
|
||||||
username: 'user1',
|
username: 'user1',
|
||||||
displayName: 'user 1'
|
displayName: 'user 1'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should detect a signup as SPAM', async function () {
|
it('Should detect a signup as SPAM', async function () {
|
||||||
await servers[0].users.register({
|
await servers[0].registrations.register({
|
||||||
username: 'user2',
|
username: 'user2',
|
||||||
displayName: 'user 2',
|
displayName: 'user 2',
|
||||||
email: 'akismet-guaranteed-spam@example.com',
|
email: 'akismet-guaranteed-spam@example.com',
|
||||||
|
|
|
@ -226,16 +226,29 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
registerHook({
|
{
|
||||||
target: 'filter:api.user.signup.allowed.result',
|
registerHook({
|
||||||
handler: (result, params) => {
|
target: 'filter:api.user.signup.allowed.result',
|
||||||
if (params && params.body && params.body.email && params.body.email.includes('jma')) {
|
handler: (result, params) => {
|
||||||
return { allowed: false, errorMessage: 'No jma' }
|
if (params && params.body && params.body.email && params.body.email.includes('jma 1')) {
|
||||||
}
|
return { allowed: false, errorMessage: 'No jma 1' }
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
registerHook({
|
||||||
|
target: 'filter:api.user.request-signup.allowed.result',
|
||||||
|
handler: (result, params) => {
|
||||||
|
if (params && params.body && params.body.email && params.body.email.includes('jma 2')) {
|
||||||
|
return { allowed: false, errorMessage: 'No jma 2' }
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
registerHook({
|
registerHook({
|
||||||
target: 'filter:api.download.torrent.allowed.result',
|
target: 'filter:api.download.torrent.allowed.result',
|
||||||
|
|
|
@ -153,7 +153,7 @@ describe('Test plugin action hooks', function () {
|
||||||
let userId: number
|
let userId: number
|
||||||
|
|
||||||
it('Should run action:api.user.registered', async function () {
|
it('Should run action:api.user.registered', async function () {
|
||||||
await servers[0].users.register({ username: 'registered_user' })
|
await servers[0].registrations.register({ username: 'registered_user' })
|
||||||
|
|
||||||
await checkHook('action:api.user.registered')
|
await checkHook('action:api.user.registered')
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||||
|
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { HttpStatusCode, VideoDetails, VideoImportState, VideoPlaylist, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
|
import {
|
||||||
|
HttpStatusCode,
|
||||||
|
PeerTubeProblemDocument,
|
||||||
|
VideoDetails,
|
||||||
|
VideoImportState,
|
||||||
|
VideoPlaylist,
|
||||||
|
VideoPlaylistPrivacy,
|
||||||
|
VideoPrivacy
|
||||||
|
} from '@shared/models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createMultipleServers,
|
createMultipleServers,
|
||||||
|
@ -408,23 +416,52 @@ describe('Test plugin filter hooks', function () {
|
||||||
|
|
||||||
describe('Should run filter:api.user.signup.allowed.result', function () {
|
describe('Should run filter:api.user.signup.allowed.result', function () {
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
await servers[0].config.updateExistingSubConfig({ newConfig: { signup: { requiresApproval: false } } })
|
||||||
|
})
|
||||||
|
|
||||||
it('Should run on config endpoint', async function () {
|
it('Should run on config endpoint', async function () {
|
||||||
const body = await servers[0].config.getConfig()
|
const body = await servers[0].config.getConfig()
|
||||||
expect(body.signup.allowed).to.be.true
|
expect(body.signup.allowed).to.be.true
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should allow a signup', async function () {
|
it('Should allow a signup', async function () {
|
||||||
await servers[0].users.register({ username: 'john', password: 'password' })
|
await servers[0].registrations.register({ username: 'john1' })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not allow a signup', async function () {
|
it('Should not allow a signup', async function () {
|
||||||
const res = await servers[0].users.register({
|
const res = await servers[0].registrations.register({
|
||||||
username: 'jma',
|
username: 'jma 1',
|
||||||
password: 'password',
|
|
||||||
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(res.body.error).to.equal('No jma')
|
expect(res.body.error).to.equal('No jma 1')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Should run filter:api.user.request-signup.allowed.result', function () {
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
await servers[0].config.updateExistingSubConfig({ newConfig: { signup: { requiresApproval: true } } })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should run on config endpoint', async function () {
|
||||||
|
const body = await servers[0].config.getConfig()
|
||||||
|
expect(body.signup.allowed).to.be.true
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should allow a signup request', async function () {
|
||||||
|
await servers[0].registrations.requestRegistration({ username: 'john2', registrationReason: 'tt' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should not allow a signup request', async function () {
|
||||||
|
const body = await servers[0].registrations.requestRegistration({
|
||||||
|
username: 'jma 2',
|
||||||
|
registrationReason: 'tt',
|
||||||
|
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||||
|
})
|
||||||
|
|
||||||
|
expect((body as unknown as PeerTubeProblemDocument).error).to.equal('No jma 2')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
UserNotificationType
|
UserNotificationType
|
||||||
} from '@shared/models'
|
} from '@shared/models'
|
||||||
import {
|
import {
|
||||||
|
ConfigCommand,
|
||||||
createMultipleServers,
|
createMultipleServers,
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
PeerTubeServer,
|
PeerTubeServer,
|
||||||
|
@ -173,6 +174,8 @@ async function checkMyVideoImportIsFinished (options: CheckerBaseParams & {
|
||||||
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
|
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
async function checkUserRegistered (options: CheckerBaseParams & {
|
async function checkUserRegistered (options: CheckerBaseParams & {
|
||||||
username: string
|
username: string
|
||||||
checkType: CheckerType
|
checkType: CheckerType
|
||||||
|
@ -201,6 +204,36 @@ async function checkUserRegistered (options: CheckerBaseParams & {
|
||||||
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
|
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkRegistrationRequest (options: CheckerBaseParams & {
|
||||||
|
username: string
|
||||||
|
registrationReason: string
|
||||||
|
checkType: CheckerType
|
||||||
|
}) {
|
||||||
|
const { username, registrationReason } = options
|
||||||
|
const notificationType = UserNotificationType.NEW_USER_REGISTRATION_REQUEST
|
||||||
|
|
||||||
|
function notificationChecker (notification: UserNotification, checkType: CheckerType) {
|
||||||
|
if (checkType === 'presence') {
|
||||||
|
expect(notification).to.not.be.undefined
|
||||||
|
expect(notification.type).to.equal(notificationType)
|
||||||
|
|
||||||
|
expect(notification.registration.username).to.equal(username)
|
||||||
|
} else {
|
||||||
|
expect(notification).to.satisfy(n => n.type !== notificationType || n.registration.username !== username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function emailNotificationFinder (email: object) {
|
||||||
|
const text: string = email['text']
|
||||||
|
|
||||||
|
return text.includes(' wants to register ') && text.includes(username) && text.includes(registrationReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
async function checkNewActorFollow (options: CheckerBaseParams & {
|
async function checkNewActorFollow (options: CheckerBaseParams & {
|
||||||
followType: 'channel' | 'account'
|
followType: 'channel' | 'account'
|
||||||
followerName: string
|
followerName: string
|
||||||
|
@ -673,10 +706,8 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
|
||||||
const port = await MockSmtpServer.Instance.collectEmails(emails)
|
const port = await MockSmtpServer.Instance.collectEmails(emails)
|
||||||
|
|
||||||
const overrideConfig = {
|
const overrideConfig = {
|
||||||
smtp: {
|
...ConfigCommand.getEmailOverrideConfig(port),
|
||||||
hostname: '127.0.0.1',
|
|
||||||
port
|
|
||||||
},
|
|
||||||
signup: {
|
signup: {
|
||||||
limit: 20
|
limit: 20
|
||||||
}
|
}
|
||||||
|
@ -735,7 +766,8 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
|
||||||
userAccessToken,
|
userAccessToken,
|
||||||
emails,
|
emails,
|
||||||
servers,
|
servers,
|
||||||
channelId
|
channelId,
|
||||||
|
baseOverrideConfig: overrideConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,7 +797,8 @@ export {
|
||||||
checkNewAccountAbuseForModerators,
|
checkNewAccountAbuseForModerators,
|
||||||
checkNewPeerTubeVersion,
|
checkNewPeerTubeVersion,
|
||||||
checkNewPluginVersion,
|
checkNewPluginVersion,
|
||||||
checkVideoStudioEditionIsFinished
|
checkVideoStudioEditionIsFinished,
|
||||||
|
checkRegistrationRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -18,6 +18,33 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static getEmailOverrideConfig (emailPort: number) {
|
||||||
|
return {
|
||||||
|
smtp: {
|
||||||
|
hostname: '127.0.0.1',
|
||||||
|
port: emailPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enableSignup (requiresApproval: boolean) {
|
||||||
|
return this.updateExistingSubConfig({
|
||||||
|
newConfig: {
|
||||||
|
signup: {
|
||||||
|
enabled: true,
|
||||||
|
requiresApproval,
|
||||||
|
limit: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
disableImports () {
|
disableImports () {
|
||||||
return this.setImportsEnabled(false)
|
return this.setImportsEnabled(false)
|
||||||
}
|
}
|
||||||
|
@ -44,6 +71,16 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enableChannelSync () {
|
||||||
|
return this.setChannelSyncEnabled(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
disableChannelSync () {
|
||||||
|
return this.setChannelSyncEnabled(false)
|
||||||
|
}
|
||||||
|
|
||||||
private setChannelSyncEnabled (enabled: boolean) {
|
private setChannelSyncEnabled (enabled: boolean) {
|
||||||
return this.updateExistingSubConfig({
|
return this.updateExistingSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
|
@ -56,13 +93,7 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
enableChannelSync () {
|
// ---------------------------------------------------------------------------
|
||||||
return this.setChannelSyncEnabled(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
disableChannelSync () {
|
|
||||||
return this.setChannelSyncEnabled(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
enableLive (options: {
|
enableLive (options: {
|
||||||
allowReplay?: boolean
|
allowReplay?: boolean
|
||||||
|
@ -142,6 +173,8 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
enableStudio () {
|
enableStudio () {
|
||||||
return this.updateExistingSubConfig({
|
return this.updateExistingSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
|
@ -152,6 +185,8 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
getConfig (options: OverrideCommandOptions = {}) {
|
getConfig (options: OverrideCommandOptions = {}) {
|
||||||
const path = '/api/v1/config'
|
const path = '/api/v1/config'
|
||||||
|
|
||||||
|
@ -304,6 +339,7 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
signup: {
|
signup: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
limit: 5,
|
limit: 5,
|
||||||
|
requiresApproval: true,
|
||||||
requiresEmailVerification: false,
|
requiresEmailVerification: false,
|
||||||
minimumAge: 16
|
minimumAge: 16
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
BlocklistCommand,
|
BlocklistCommand,
|
||||||
LoginCommand,
|
LoginCommand,
|
||||||
NotificationsCommand,
|
NotificationsCommand,
|
||||||
|
RegistrationsCommand,
|
||||||
SubscriptionsCommand,
|
SubscriptionsCommand,
|
||||||
TwoFactorCommand,
|
TwoFactorCommand,
|
||||||
UsersCommand
|
UsersCommand
|
||||||
|
@ -147,6 +148,7 @@ export class PeerTubeServer {
|
||||||
views?: ViewsCommand
|
views?: ViewsCommand
|
||||||
twoFactor?: TwoFactorCommand
|
twoFactor?: TwoFactorCommand
|
||||||
videoToken?: VideoTokenCommand
|
videoToken?: VideoTokenCommand
|
||||||
|
registrations?: RegistrationsCommand
|
||||||
|
|
||||||
constructor (options: { serverNumber: number } | { url: string }) {
|
constructor (options: { serverNumber: number } | { url: string }) {
|
||||||
if ((options as any).url) {
|
if ((options as any).url) {
|
||||||
|
@ -430,5 +432,6 @@ export class PeerTubeServer {
|
||||||
this.views = new ViewsCommand(this)
|
this.views = new ViewsCommand(this)
|
||||||
this.twoFactor = new TwoFactorCommand(this)
|
this.twoFactor = new TwoFactorCommand(this)
|
||||||
this.videoToken = new VideoTokenCommand(this)
|
this.videoToken = new VideoTokenCommand(this)
|
||||||
|
this.registrations = new RegistrationsCommand(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ export * from './blocklist-command'
|
||||||
export * from './login'
|
export * from './login'
|
||||||
export * from './login-command'
|
export * from './login-command'
|
||||||
export * from './notifications-command'
|
export * from './notifications-command'
|
||||||
|
export * from './registrations-command'
|
||||||
export * from './subscriptions-command'
|
export * from './subscriptions-command'
|
||||||
export * from './two-factor-command'
|
export * from './two-factor-command'
|
||||||
export * from './users-command'
|
export * from './users-command'
|
||||||
|
|
157
shared/server-commands/users/registrations-command.ts
Normal file
157
shared/server-commands/users/registrations-command.ts
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
import { pick } from '@shared/core-utils'
|
||||||
|
import { HttpStatusCode, ResultList, UserRegistration, UserRegistrationRequest } from '@shared/models'
|
||||||
|
import { unwrapBody } from '../requests'
|
||||||
|
import { AbstractCommand, OverrideCommandOptions } from '../shared'
|
||||||
|
|
||||||
|
export class RegistrationsCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
register (options: OverrideCommandOptions & Partial<UserRegistrationRequest> & Pick<UserRegistrationRequest, 'username'>) {
|
||||||
|
const { password = 'password', email = options.username + '@example.com' } = options
|
||||||
|
const path = '/api/v1/users/register'
|
||||||
|
|
||||||
|
return this.postBodyRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
fields: {
|
||||||
|
...pick(options, [ 'username', 'displayName', 'channel' ]),
|
||||||
|
|
||||||
|
password,
|
||||||
|
email
|
||||||
|
},
|
||||||
|
implicitToken: false,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
requestRegistration (
|
||||||
|
options: OverrideCommandOptions & Partial<UserRegistrationRequest> & Pick<UserRegistrationRequest, 'username' | 'registrationReason'>
|
||||||
|
) {
|
||||||
|
const { password = 'password', email = options.username + '@example.com' } = options
|
||||||
|
const path = '/api/v1/users/registrations/request'
|
||||||
|
|
||||||
|
return unwrapBody<UserRegistration>(this.postBodyRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
fields: {
|
||||||
|
...pick(options, [ 'username', 'displayName', 'channel', 'registrationReason' ]),
|
||||||
|
|
||||||
|
password,
|
||||||
|
email
|
||||||
|
},
|
||||||
|
implicitToken: false,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.OK_200
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
accept (options: OverrideCommandOptions & {
|
||||||
|
id: number
|
||||||
|
moderationResponse: string
|
||||||
|
}) {
|
||||||
|
const { id, moderationResponse } = options
|
||||||
|
const path = '/api/v1/users/registrations/' + id + '/accept'
|
||||||
|
|
||||||
|
return this.postBodyRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
fields: { moderationResponse },
|
||||||
|
implicitToken: true,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
reject (options: OverrideCommandOptions & {
|
||||||
|
id: number
|
||||||
|
moderationResponse: string
|
||||||
|
}) {
|
||||||
|
const { id, moderationResponse } = options
|
||||||
|
const path = '/api/v1/users/registrations/' + id + '/reject'
|
||||||
|
|
||||||
|
return this.postBodyRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
fields: { moderationResponse },
|
||||||
|
implicitToken: true,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
delete (options: OverrideCommandOptions & {
|
||||||
|
id: number
|
||||||
|
}) {
|
||||||
|
const { id } = options
|
||||||
|
const path = '/api/v1/users/registrations/' + id
|
||||||
|
|
||||||
|
return this.deleteRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
implicitToken: true,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
list (options: OverrideCommandOptions & {
|
||||||
|
start?: number
|
||||||
|
count?: number
|
||||||
|
sort?: string
|
||||||
|
search?: string
|
||||||
|
} = {}) {
|
||||||
|
const path = '/api/v1/users/registrations'
|
||||||
|
|
||||||
|
return this.getRequestBody<ResultList<UserRegistration>>({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
query: pick(options, [ 'start', 'count', 'sort', 'search' ]),
|
||||||
|
implicitToken: true,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.OK_200
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
askSendVerifyEmail (options: OverrideCommandOptions & {
|
||||||
|
email: string
|
||||||
|
}) {
|
||||||
|
const { email } = options
|
||||||
|
const path = '/api/v1/users/registrations/ask-send-verify-email'
|
||||||
|
|
||||||
|
return this.postBodyRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
fields: { email },
|
||||||
|
implicitToken: false,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyEmail (options: OverrideCommandOptions & {
|
||||||
|
registrationId: number
|
||||||
|
verificationString: string
|
||||||
|
}) {
|
||||||
|
const { registrationId, verificationString } = options
|
||||||
|
const path = '/api/v1/users/registrations/' + registrationId + '/verify-email'
|
||||||
|
|
||||||
|
return this.postBodyRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
fields: {
|
||||||
|
verificationString
|
||||||
|
},
|
||||||
|
implicitToken: false,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -214,35 +214,6 @@ export class UsersCommand extends AbstractCommand {
|
||||||
return this.server.login.getAccessToken({ username, password })
|
return this.server.login.getAccessToken({ username, password })
|
||||||
}
|
}
|
||||||
|
|
||||||
register (options: OverrideCommandOptions & {
|
|
||||||
username: string
|
|
||||||
password?: string
|
|
||||||
displayName?: string
|
|
||||||
email?: string
|
|
||||||
channel?: {
|
|
||||||
name: string
|
|
||||||
displayName: string
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
const { username, password = 'password', displayName, channel, email = username + '@example.com' } = options
|
|
||||||
const path = '/api/v1/users/register'
|
|
||||||
|
|
||||||
return this.postBodyRequest({
|
|
||||||
...options,
|
|
||||||
|
|
||||||
path,
|
|
||||||
fields: {
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
email,
|
|
||||||
displayName,
|
|
||||||
channel
|
|
||||||
},
|
|
||||||
implicitToken: false,
|
|
||||||
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
getMyInfo (options: OverrideCommandOptions = {}) {
|
getMyInfo (options: OverrideCommandOptions = {}) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user