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,
setDefaultAccountAvatar,
setDefaultChannelAvatar
} 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 setDefaultAccountAvatar([ server ])
await setDefaultChannelAvatar([ 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 server.config.enableSignup(false)
await makePostBodyRequest({ url: server.url, path: registrationPath, fields, expectedStatus })
await server.config.enableSignup(true)
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.updateExistingSubConfig({
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.enableSignup(false, total)
await server.registrations.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
await server.config.enableSignup(true, total)
await server.registrations.requestRegistration({
username: 'user42',
registrationReason: 'reason',
expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
it('Should succeed if the user limit is not reached', async function () {
this.timeout(60000)
const { total } = await server.users.list()
await server.config.enableSignup(false, total + 1)
await server.registrations.register({ username: 'user43', expectedStatus: HttpStatusCode.NO_CONTENT_204 })
await server.config.enableSignup(true, total + 2)
await server.registrations.requestRegistration({
username: 'user44',
registrationReason: 'reason',
expectedStatus: HttpStatusCode.OK_200
})
})
})
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 username 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 email is already awaiting registration approval', async function () {
await server.registrations.requestRegistration({
username: 'user42',
email: 'user_request_2@example.com',
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 ])
})
})