Skip to content

Commit f5ac42c

Browse files
authored
feat(server): add a new PUT method to create a key with a specific identifier (#1473)
* feat(server): add optional `id` parameter to `createNewAccessKey` method * Use `PUT` instead of `POST`. * Make changes based on review. * Update access key creation path to only allow ID on `PUT` calls. * Expand test scenarios for key generation to `createAccessKey`. * Add a `toHavePropertiesOf` custom Jasmine matcher. * Add explicit test case for `ConflictError`. * Revert "Add a `toHavePropertiesOf` custom Jasmine matcher." This reverts commit 134e0df.
1 parent 57a30a2 commit f5ac42c

7 files changed

+400
-197
lines changed

src/shadowbox/model/access_key.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export interface AccessKey {
4949
}
5050

5151
export interface AccessKeyCreateParams {
52+
// The unique identifier to give the access key. Throws if it exists.
53+
readonly id?: AccessKeyId;
5254
// The encryption method to use for the access key.
5355
readonly encryptionMethod?: string;
5456
// The name to give the access key.
@@ -60,7 +62,7 @@ export interface AccessKeyCreateParams {
6062
}
6163

6264
export interface AccessKeyRepository {
63-
// Creates a new access key. Parameters are chosen automatically.
65+
// Creates a new access key. Parameters are chosen automatically if not provided.
6466
createNewAccessKey(params?: AccessKeyCreateParams): Promise<AccessKey>;
6567
// Removes the access key given its id. Throws on failure.
6668
removeAccessKey(id: AccessKeyId);

src/shadowbox/model/errors.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
import {AccessKeyId} from './access_key';
16+
1517
// TODO(fortuna): Reuse CustomError from server_manager.
1618
class OutlineError extends Error {
1719
constructor(message: string) {
@@ -35,7 +37,7 @@ export class PortUnavailable extends OutlineError {
3537
}
3638

3739
export class AccessKeyNotFound extends OutlineError {
38-
constructor(accessKeyId?: string) {
40+
constructor(accessKeyId?: AccessKeyId) {
3941
super(`Access key "${accessKeyId}" not found`);
4042
}
4143
}
@@ -45,3 +47,9 @@ export class InvalidCipher extends OutlineError {
4547
super(`cipher "${cipher}" is not valid`);
4648
}
4749
}
50+
51+
export class AccessKeyConflict extends OutlineError {
52+
constructor(accessKeyId?: AccessKeyId) {
53+
super(`Access key "${accessKeyId}" conflict`);
54+
}
55+
}

src/shadowbox/server/api.yml

+44-5
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ paths:
3737
- Server
3838
description: Changes the hostname for access keys. Must be a valid hostname or IP address. If it's a hostname, DNS must be set up independently of this API.
3939
requestBody:
40-
required: true
40+
required: true
4141
content:
4242
application/json:
4343
schema:
@@ -51,7 +51,7 @@ paths:
5151
'IP address':
5252
value: '{"hostname": "127.0.0.1"}'
5353
responses:
54-
'204':
54+
'204':
5555
description: The hostname was successfully changed.
5656
'400':
5757
description: An invalid hostname or IP address was provided.
@@ -82,7 +82,7 @@ paths:
8282
description: The requested port wasn't an integer from 1 through 65535, or the request had no port parameter.
8383
'409':
8484
description: The requested port was already in use by another service.
85-
85+
8686
/server/access-key-data-limit:
8787
put:
8888
description: Sets a data transfer limit for all access keys
@@ -157,7 +157,9 @@ paths:
157157
dataLimit:
158158
$ref: "#/components/schemas/DataLimit"
159159
examples:
160-
'0':
160+
'No params specified':
161+
value: '{"method":"aes-192-gcm"}'
162+
'Provide params':
161163
value: '{"method":"aes-192-gcm","name":"First","password":"8iu8V8EeoFVpwQvQeS9wiD","limit":{"bytes":10000}}'
162164
responses:
163165
'201':
@@ -173,6 +175,43 @@ paths:
173175
'1':
174176
value: >-
175177
{"id":"1","name":"Second","password":"xXxXxX","port":9795,"method":"chacha20-ietf-poly1305","accessUrl":"ss://ASDFHAKSDFSDAKFJ@0.0.0.0:9795/?outline=1"}
178+
put:
179+
description: Creates a new access key with a specific identifer
180+
tags:
181+
- Access Key
182+
requestBody:
183+
required: false
184+
content:
185+
application/json:
186+
schema:
187+
type: object
188+
properties:
189+
id:
190+
type: string
191+
name:
192+
type: string
193+
method:
194+
type: string
195+
password:
196+
type: string
197+
port:
198+
type: integer
199+
dataLimit:
200+
$ref: "#/components/schemas/DataLimit"
201+
examples:
202+
'0':
203+
value: '{"id":"123","method":"aes-192-gcm","name":"First","password":"8iu8V8EeoFVpwQvQeS9wiD","limit":{"bytes":10000}}'
204+
responses:
205+
'201':
206+
description: The newly created access key
207+
content:
208+
application/json:
209+
schema:
210+
$ref: "#/components/schemas/AccessKey"
211+
examples:
212+
'0':
213+
value: >-
214+
{"id":"my-identifier","name":"First","password":"XxXxXx","port":9795,"method":"chacha20-ietf-poly1305","accessUrl":"ss://SADFJSKADFJAKSD@0.0.0.0:9795/?outline=1"}
176215
get:
177216
description: Lists the access keys
178217
tags:
@@ -427,7 +466,7 @@ paths:
427466
responses:
428467
'204':
429468
description: Access key limit deleted successfully.
430-
469+
431470
components:
432471
schemas:
433472
Server:

0 commit comments

Comments
 (0)