diff options
author | Chocobozzz <me@florianbigard.com> | 2022-08-03 10:10:26 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2022-08-03 10:10:26 +0200 |
commit | 0b6f531653a7a24f82ad65564479a70a9326301a (patch) | |
tree | f65d9c80e0e8ced86a8a9f7b00952bb04413a5b7 /server/lib | |
parent | 35a0a924830d84f9ec28c129ec85cb1f45011fb8 (diff) | |
download | PeerTube-0b6f531653a7a24f82ad65564479a70a9326301a.tar.gz PeerTube-0b6f531653a7a24f82ad65564479a70a9326301a.tar.zst PeerTube-0b6f531653a7a24f82ad65564479a70a9326301a.zip |
Suffix external auth username on conflict
Diffstat (limited to 'server/lib')
-rw-r--r-- | server/lib/auth/oauth-model.ts | 9 | ||||
-rw-r--r-- | server/lib/local-actor.ts | 18 | ||||
-rw-r--r-- | server/lib/user.ts | 17 |
3 files changed, 30 insertions, 14 deletions
diff --git a/server/lib/auth/oauth-model.ts b/server/lib/auth/oauth-model.ts index d9cf32827..322b69e3a 100644 --- a/server/lib/auth/oauth-model.ts +++ b/server/lib/auth/oauth-model.ts | |||
@@ -1,7 +1,6 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { AccessDeniedError } from '@node-oauth/oauth2-server' | 2 | import { AccessDeniedError } from '@node-oauth/oauth2-server' |
3 | import { PluginManager } from '@server/lib/plugins/plugin-manager' | 3 | import { PluginManager } from '@server/lib/plugins/plugin-manager' |
4 | import { ActorModel } from '@server/models/actor/actor' | ||
5 | import { MOAuthClient } from '@server/types/models' | 4 | import { MOAuthClient } from '@server/types/models' |
6 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' | 5 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' |
7 | import { MUser } from '@server/types/models/user/user' | 6 | import { MUser } from '@server/types/models/user/user' |
@@ -12,6 +11,7 @@ import { CONFIG } from '../../initializers/config' | |||
12 | import { OAuthClientModel } from '../../models/oauth/oauth-client' | 11 | import { OAuthClientModel } from '../../models/oauth/oauth-client' |
13 | import { OAuthTokenModel } from '../../models/oauth/oauth-token' | 12 | import { OAuthTokenModel } from '../../models/oauth/oauth-token' |
14 | import { UserModel } from '../../models/user/user' | 13 | import { UserModel } from '../../models/user/user' |
14 | import { findAvailableLocalActorName } from '../local-actor' | ||
15 | import { buildUser, createUserAccountAndChannelAndPlaylist } from '../user' | 15 | import { buildUser, createUserAccountAndChannelAndPlaylist } from '../user' |
16 | import { TokensCache } from './tokens-cache' | 16 | import { TokensCache } from './tokens-cache' |
17 | 17 | ||
@@ -225,13 +225,12 @@ async function createUserFromExternal (pluginAuth: string, options: { | |||
225 | role: UserRole | 225 | role: UserRole |
226 | displayName: string | 226 | displayName: string |
227 | }) { | 227 | }) { |
228 | // Check an actor does not already exists with that name (removed user) | 228 | const username = await findAvailableLocalActorName(options.username) |
229 | const actor = await ActorModel.loadLocalByName(options.username) | ||
230 | if (actor) return null | ||
231 | 229 | ||
232 | const userToCreate = buildUser({ | 230 | const userToCreate = buildUser({ |
233 | ...pick(options, [ 'username', 'email', 'role' ]), | 231 | ...pick(options, [ 'email', 'role' ]), |
234 | 232 | ||
233 | username, | ||
235 | emailVerified: null, | 234 | emailVerified: null, |
236 | password: null, | 235 | password: null, |
237 | pluginAuth | 236 | pluginAuth |
diff --git a/server/lib/local-actor.ts b/server/lib/local-actor.ts index 1d9be76e2..8c10ed700 100644 --- a/server/lib/local-actor.ts +++ b/server/lib/local-actor.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { remove } from 'fs-extra' | 1 | import { remove } from 'fs-extra' |
2 | import LRUCache from 'lru-cache' | 2 | import LRUCache from 'lru-cache' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { Transaction } from 'sequelize/types' | ||
4 | import { ActorModel } from '@server/models/actor/actor' | 5 | import { ActorModel } from '@server/models/actor/actor' |
5 | import { getLowercaseExtension } from '@shared/core-utils' | 6 | import { getLowercaseExtension } from '@shared/core-utils' |
6 | import { buildUUID } from '@shared/extra-utils' | 7 | import { buildUUID } from '@shared/extra-utils' |
@@ -87,6 +88,22 @@ async function deleteLocalActorImageFile (accountOrChannel: MAccountDefault | MC | |||
87 | 88 | ||
88 | // --------------------------------------------------------------------------- | 89 | // --------------------------------------------------------------------------- |
89 | 90 | ||
91 | async function findAvailableLocalActorName (baseActorName: string, transaction?: Transaction) { | ||
92 | let actor = await ActorModel.loadLocalByName(baseActorName, transaction) | ||
93 | if (!actor) return baseActorName | ||
94 | |||
95 | for (let i = 1; i < 30; i++) { | ||
96 | const name = `${baseActorName}-${i}` | ||
97 | |||
98 | actor = await ActorModel.loadLocalByName(name, transaction) | ||
99 | if (!actor) return name | ||
100 | } | ||
101 | |||
102 | throw new Error('Cannot find available actor local name (too much iterations).') | ||
103 | } | ||
104 | |||
105 | // --------------------------------------------------------------------------- | ||
106 | |||
90 | function downloadActorImageFromWorker (options: { | 107 | function downloadActorImageFromWorker (options: { |
91 | fileUrl: string | 108 | fileUrl: string |
92 | filename: string | 109 | filename: string |
@@ -109,6 +126,7 @@ const actorImagePathUnsafeCache = new LRUCache<string, string>({ max: LRU_CACHE. | |||
109 | export { | 126 | export { |
110 | actorImagePathUnsafeCache, | 127 | actorImagePathUnsafeCache, |
111 | updateLocalActorImageFiles, | 128 | updateLocalActorImageFiles, |
129 | findAvailableLocalActorName, | ||
112 | downloadActorImageFromWorker, | 130 | downloadActorImageFromWorker, |
113 | deleteLocalActorImageFile, | 131 | deleteLocalActorImageFile, |
114 | downloadImageFromWorker, | 132 | downloadImageFromWorker, |
diff --git a/server/lib/user.ts b/server/lib/user.ts index f4ffae0e4..2e433da04 100644 --- a/server/lib/user.ts +++ b/server/lib/user.ts | |||
@@ -3,13 +3,11 @@ import { logger } from '@server/helpers/logger' | |||
3 | import { CONFIG } from '@server/initializers/config' | 3 | import { CONFIG } from '@server/initializers/config' |
4 | import { UserModel } from '@server/models/user/user' | 4 | import { UserModel } from '@server/models/user/user' |
5 | import { MActorDefault } from '@server/types/models/actor' | 5 | import { MActorDefault } from '@server/types/models/actor' |
6 | import { buildUUID } from '@shared/extra-utils' | ||
7 | import { ActivityPubActorType } from '../../shared/models/activitypub' | 6 | import { ActivityPubActorType } from '../../shared/models/activitypub' |
8 | import { UserAdminFlag, UserNotificationSetting, UserNotificationSettingValue, UserRole } from '../../shared/models/users' | 7 | import { UserAdminFlag, UserNotificationSetting, UserNotificationSettingValue, UserRole } from '../../shared/models/users' |
9 | import { SERVER_ACTOR_NAME, WEBSERVER } from '../initializers/constants' | 8 | import { SERVER_ACTOR_NAME, WEBSERVER } from '../initializers/constants' |
10 | import { sequelizeTypescript } from '../initializers/database' | 9 | import { sequelizeTypescript } from '../initializers/database' |
11 | import { AccountModel } from '../models/account/account' | 10 | import { AccountModel } from '../models/account/account' |
12 | import { ActorModel } from '../models/actor/actor' | ||
13 | import { UserNotificationSettingModel } from '../models/user/user-notification-setting' | 11 | import { UserNotificationSettingModel } from '../models/user/user-notification-setting' |
14 | import { MAccountDefault, MChannelActor } from '../types/models' | 12 | import { MAccountDefault, MChannelActor } from '../types/models' |
15 | import { MUser, MUserDefault, MUserId } from '../types/models/user' | 13 | import { MUser, MUserDefault, MUserId } from '../types/models/user' |
@@ -17,7 +15,7 @@ import { generateAndSaveActorKeys } from './activitypub/actors' | |||
17 | import { getLocalAccountActivityPubUrl } from './activitypub/url' | 15 | import { getLocalAccountActivityPubUrl } from './activitypub/url' |
18 | import { Emailer } from './emailer' | 16 | import { Emailer } from './emailer' |
19 | import { LiveQuotaStore } from './live/live-quota-store' | 17 | import { LiveQuotaStore } from './live/live-quota-store' |
20 | import { buildActorInstance } from './local-actor' | 18 | import { buildActorInstance, findAvailableLocalActorName } from './local-actor' |
21 | import { Redis } from './redis' | 19 | import { Redis } from './redis' |
22 | import { createLocalVideoChannel } from './video-channel' | 20 | import { createLocalVideoChannel } from './video-channel' |
23 | import { createWatchLaterPlaylist } from './video-playlist' | 21 | import { createWatchLaterPlaylist } from './video-playlist' |
@@ -71,6 +69,8 @@ function buildUser (options: { | |||
71 | }) | 69 | }) |
72 | } | 70 | } |
73 | 71 | ||
72 | // --------------------------------------------------------------------------- | ||
73 | |||
74 | async function createUserAccountAndChannelAndPlaylist (parameters: { | 74 | async function createUserAccountAndChannelAndPlaylist (parameters: { |
75 | userToCreate: MUser | 75 | userToCreate: MUser |
76 | userDisplayName?: string | 76 | userDisplayName?: string |
@@ -157,6 +157,8 @@ async function createApplicationActor (applicationId: number) { | |||
157 | return accountCreated | 157 | return accountCreated |
158 | } | 158 | } |
159 | 159 | ||
160 | // --------------------------------------------------------------------------- | ||
161 | |||
160 | async function sendVerifyUserEmail (user: MUser, isPendingEmail = false) { | 162 | async function sendVerifyUserEmail (user: MUser, isPendingEmail = false) { |
161 | const verificationString = await Redis.Instance.setVerifyEmailVerificationString(user.id) | 163 | const verificationString = await Redis.Instance.setVerifyEmailVerificationString(user.id) |
162 | let url = WEBSERVER.URL + '/verify-account/email?userId=' + user.id + '&verificationString=' + verificationString | 164 | let url = WEBSERVER.URL + '/verify-account/email?userId=' + user.id + '&verificationString=' + verificationString |
@@ -169,6 +171,8 @@ async function sendVerifyUserEmail (user: MUser, isPendingEmail = false) { | |||
169 | Emailer.Instance.addVerifyEmailJob(username, email, url) | 171 | Emailer.Instance.addVerifyEmailJob(username, email, url) |
170 | } | 172 | } |
171 | 173 | ||
174 | // --------------------------------------------------------------------------- | ||
175 | |||
172 | async function getOriginalVideoFileTotalFromUser (user: MUserId) { | 176 | async function getOriginalVideoFileTotalFromUser (user: MUserId) { |
173 | // Don't use sequelize because we need to use a sub query | 177 | // Don't use sequelize because we need to use a sub query |
174 | const query = UserModel.generateUserQuotaBaseSQL({ | 178 | const query = UserModel.generateUserQuotaBaseSQL({ |
@@ -263,12 +267,7 @@ function createDefaultUserNotificationSettings (user: MUserId, t: Transaction | | |||
263 | async function buildChannelAttributes (user: MUser, transaction?: Transaction, channelNames?: ChannelNames) { | 267 | async function buildChannelAttributes (user: MUser, transaction?: Transaction, channelNames?: ChannelNames) { |
264 | if (channelNames) return channelNames | 268 | if (channelNames) return channelNames |
265 | 269 | ||
266 | let channelName = user.username + '_channel' | 270 | const channelName = await findAvailableLocalActorName(user.username + '_channel', transaction) |
267 | |||
268 | // Conflict, generate uuid instead | ||
269 | const actor = await ActorModel.loadLocalByName(channelName, transaction) | ||
270 | if (actor) channelName = buildUUID() | ||
271 | |||
272 | const videoChannelDisplayName = `Main ${user.username} channel` | 271 | const videoChannelDisplayName = `Main ${user.username} channel` |
273 | 272 | ||
274 | return { | 273 | return { |