mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: allows creation of PATs for other users (#2718)
https://linear.app/unleash/issue/2-530/api-allow-creation-of-pats-for-other-users  Adds and takes into account the following permissions: - **READ_USER_PAT**; - **CREATE_USER_PAT**; - **DELETE_USER_PAT**; API only, will make some exploration on UI soon. Co-authored-by: Gastón Fournier <gaston@getunleash.ai>
This commit is contained in:
		
							parent
							
								
									aab809cac3
								
							
						
					
					
						commit
						88004a6138
					
				| @ -36,3 +36,6 @@ export const DELETE_SEGMENT = 'DELETE_SEGMENT'; | |||||||
| export const APPLY_CHANGE_REQUEST = 'APPLY_CHANGE_REQUEST'; | export const APPLY_CHANGE_REQUEST = 'APPLY_CHANGE_REQUEST'; | ||||||
| export const APPROVE_CHANGE_REQUEST = 'APPROVE_CHANGE_REQUEST'; | export const APPROVE_CHANGE_REQUEST = 'APPROVE_CHANGE_REQUEST'; | ||||||
| export const SKIP_CHANGE_REQUEST = 'SKIP_CHANGE_REQUEST'; | export const SKIP_CHANGE_REQUEST = 'SKIP_CHANGE_REQUEST'; | ||||||
|  | export const READ_USER_PAT = 'READ_USER_PAT'; | ||||||
|  | export const CREATE_USER_PAT = 'CREATE_USER_PAT'; | ||||||
|  | export const DELETE_USER_PAT = 'DELETE_USER_PAT'; | ||||||
|  | |||||||
| @ -80,6 +80,7 @@ exports[`should create default config 1`] = ` | |||||||
|       "networkView": false, |       "networkView": false, | ||||||
|       "proxyReturnAllToggles": false, |       "proxyReturnAllToggles": false, | ||||||
|       "responseTimeWithAppName": false, |       "responseTimeWithAppName": false, | ||||||
|  |       "serviceAccounts": false, | ||||||
|       "variantsPerEnvironment": false, |       "variantsPerEnvironment": false, | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
| @ -98,6 +99,7 @@ exports[`should create default config 1`] = ` | |||||||
|       "networkView": false, |       "networkView": false, | ||||||
|       "proxyReturnAllToggles": false, |       "proxyReturnAllToggles": false, | ||||||
|       "responseTimeWithAppName": false, |       "responseTimeWithAppName": false, | ||||||
|  |       "serviceAccounts": false, | ||||||
|       "variantsPerEnvironment": false, |       "variantsPerEnvironment": false, | ||||||
|     }, |     }, | ||||||
|     "externalResolver": { |     "externalResolver": { | ||||||
|  | |||||||
| @ -78,7 +78,11 @@ export default class PatController extends Controller { | |||||||
| 
 | 
 | ||||||
|     async createPat(req: IAuthRequest, res: Response): Promise<void> { |     async createPat(req: IAuthRequest, res: Response): Promise<void> { | ||||||
|         const pat = req.body; |         const pat = req.body; | ||||||
|         const createdPat = await this.patService.createPat(pat, req.user); |         const createdPat = await this.patService.createPat( | ||||||
|  |             pat, | ||||||
|  |             req.user.id, | ||||||
|  |             req.user, | ||||||
|  |         ); | ||||||
|         this.openApiService.respondWithValidation( |         this.openApiService.respondWithValidation( | ||||||
|             201, |             201, | ||||||
|             res, |             res, | ||||||
| @ -88,7 +92,7 @@ export default class PatController extends Controller { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async getPats(req: IAuthRequest, res: Response<PatSchema>): Promise<void> { |     async getPats(req: IAuthRequest, res: Response<PatSchema>): Promise<void> { | ||||||
|         const pats = await this.patService.getAll(req.user); |         const pats = await this.patService.getAll(req.user.id); | ||||||
|         this.openApiService.respondWithValidation(200, res, patsSchema.$id, { |         this.openApiService.respondWithValidation(200, res, patsSchema.$id, { | ||||||
|             pats: serializeDates(pats), |             pats: serializeDates(pats), | ||||||
|         }); |         }); | ||||||
|  | |||||||
| @ -33,24 +33,28 @@ export default class PatService { | |||||||
|         this.eventStore = eventStore; |         this.eventStore = eventStore; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async createPat(pat: IPat, user: User): Promise<IPat> { |     async createPat( | ||||||
|         await this.validatePat(pat, user.id); |         pat: IPat, | ||||||
|  |         forUserId: number, | ||||||
|  |         creator: User, | ||||||
|  |     ): Promise<IPat> { | ||||||
|  |         await this.validatePat(pat, forUserId); | ||||||
|         pat.secret = this.generateSecretKey(); |         pat.secret = this.generateSecretKey(); | ||||||
|         pat.userId = user.id; |         pat.userId = forUserId; | ||||||
|         const newPat = await this.patStore.create(pat); |         const newPat = await this.patStore.create(pat); | ||||||
| 
 | 
 | ||||||
|         pat.secret = '***'; |         pat.secret = '***'; | ||||||
|         await this.eventStore.store({ |         await this.eventStore.store({ | ||||||
|             type: PAT_CREATED, |             type: PAT_CREATED, | ||||||
|             createdBy: user.email || user.username, |             createdBy: creator.email || creator.username, | ||||||
|             data: pat, |             data: pat, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         return newPat; |         return newPat; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async getAll(user: User): Promise<IPat[]> { |     async getAll(userId: number): Promise<IPat[]> { | ||||||
|         return this.patStore.getAllByUser(user.id); |         return this.patStore.getAllByUser(userId); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async deletePat(id: number, userId: number): Promise<void> { |     async deletePat(id: number, userId: number): Promise<void> { | ||||||
|  | |||||||
| @ -51,6 +51,10 @@ const flags = { | |||||||
|         process.env.UNLEASH_EXPERIMENTAL_MESSAGE_BANNER, |         process.env.UNLEASH_EXPERIMENTAL_MESSAGE_BANNER, | ||||||
|         false, |         false, | ||||||
|     ), |     ), | ||||||
|  |     serviceAccounts: parseEnvVarBoolean( | ||||||
|  |         process.env.UNLEASH_EXPERIMENTAL_SERVICE_ACCOUNTS, | ||||||
|  |         false, | ||||||
|  |     ), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const defaultExperimentalOptions: IExperimentalOptions = { | export const defaultExperimentalOptions: IExperimentalOptions = { | ||||||
|  | |||||||
| @ -42,3 +42,6 @@ export const DELETE_SEGMENT = 'DELETE_SEGMENT'; | |||||||
| export const APPROVE_CHANGE_REQUEST = 'APPROVE_CHANGE_REQUEST'; | export const APPROVE_CHANGE_REQUEST = 'APPROVE_CHANGE_REQUEST'; | ||||||
| export const APPLY_CHANGE_REQUEST = 'APPLY_CHANGE_REQUEST'; | export const APPLY_CHANGE_REQUEST = 'APPLY_CHANGE_REQUEST'; | ||||||
| export const SKIP_CHANGE_REQUEST = 'SKIP_CHANGE_REQUEST'; | export const SKIP_CHANGE_REQUEST = 'SKIP_CHANGE_REQUEST'; | ||||||
|  | export const READ_USER_PAT = 'READ_USER_PAT'; | ||||||
|  | export const CREATE_USER_PAT = 'CREATE_USER_PAT'; | ||||||
|  | export const DELETE_USER_PAT = 'DELETE_USER_PAT'; | ||||||
|  | |||||||
							
								
								
									
										21
									
								
								src/migrations/20221220160345-user-pat-permissions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/migrations/20221220160345-user-pat-permissions.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | exports.up = function (db, cb) { | ||||||
|  |     db.runSql( | ||||||
|  |         ` | ||||||
|  |         INSERT INTO permissions (permission, display_name, type) VALUES ('READ_USER_PAT', 'Read PATs for a specific user', 'root'); | ||||||
|  |         INSERT INTO permissions (permission, display_name, type) VALUES ('CREATE_USER_PAT', 'Create a PAT for a specific user', 'root'); | ||||||
|  |         INSERT INTO permissions (permission, display_name, type) VALUES ('DELETE_USER_PAT', 'Delete a PAT for a specific user', 'root'); | ||||||
|  |         `,
 | ||||||
|  |         cb, | ||||||
|  |     ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | exports.down = function (db, cb) { | ||||||
|  |     db.runSql( | ||||||
|  |         ` | ||||||
|  |         DELETE FROM permissions WHERE permission = 'READ_USER_PAT'; | ||||||
|  |         DELETE FROM permissions WHERE permission = 'CREATE_USER_PAT'; | ||||||
|  |         DELETE FROM permissions WHERE permission = 'DELETE_USER_PAT'; | ||||||
|  |   `,
 | ||||||
|  |         cb, | ||||||
|  |     ); | ||||||
|  | }; | ||||||
| @ -41,6 +41,8 @@ process.nextTick(async () => { | |||||||
|                         responseTimeWithAppName: true, |                         responseTimeWithAppName: true, | ||||||
|                         changeRequests: true, |                         changeRequests: true, | ||||||
|                         variantsPerEnvironment: true, |                         variantsPerEnvironment: true, | ||||||
|  |                         maintenance: false, | ||||||
|  |                         serviceAccounts: true, | ||||||
|                     }, |                     }, | ||||||
|                 }, |                 }, | ||||||
|                 authentication: { |                 authentication: { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user