Skip to content

Commit

Permalink
Add new privileges for reading and writing prinicpals.
Browse files Browse the repository at this point in the history
This is a work in progress.
  • Loading branch information
evert committed Sep 25, 2023
1 parent 2a39b85 commit 89f47c0
Show file tree
Hide file tree
Showing 36 changed files with 371 additions and 412 deletions.
5 changes: 3 additions & 2 deletions src/app/controller/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import { BadRequest, Conflict, NotFound, UnprocessableEntity } from '@curveball/http-errors';
import * as hal from '../formats/hal';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';

type NewPrincipalBody = {
nickname: string;
Expand All @@ -14,14 +14,15 @@ class UserCollectionController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const apps = await principalService.findAll('app');
ctx.response.body = hal.collection(apps);

}

async post(ctx: Context) {

ctx.privileges.require('admin');
const principalService = new PrincipalService(ctx.privileges);

ctx.request.validate<NewPrincipalBody>(
'https://curveballjs.org/schemas/a12nserver/new-principal.json'
Expand Down
12 changes: 5 additions & 7 deletions src/app/controller/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import * as privilegeService from '../../privilege/service';
import * as hal from '../formats/hal';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';
import * as groupService from '../../group/service';
import { Forbidden } from '@curveball/http-errors';

type EditPrincipalBody = {
nickname: string;
Expand All @@ -26,6 +25,7 @@ class AppController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const app = await principalService.findByExternalId(ctx.params.id, 'app');

const isAdmin = ctx.privileges.has('admin');
Expand All @@ -42,14 +42,13 @@ class AppController extends Controller {

async put(ctx: Context) {

if (!ctx.privileges.has('admin')) {
throw new Forbidden('Only users with the "admin" privilege may edit users');
}
const principalService = new PrincipalService(ctx.privileges);

ctx.request.validate<EditPrincipalBody>(
'https://curveballjs.org/schemas/a12nserver/principal-edit.json'
);

const user = await principalService.findById(+ctx.params.id, 'app');
const user = await principalService.findByExternalId(ctx.params.id, 'app');
user.active = !!ctx.request.body.active;
user.nickname = ctx.request.body.nickname;

Expand All @@ -58,7 +57,6 @@ class AppController extends Controller {

}


}

export default new AppController();
4 changes: 2 additions & 2 deletions src/app/controller/new.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';
import { createAppForm } from '../formats/html';
import { uuidUrn } from '../../crypto';

Expand Down Expand Up @@ -37,7 +37,7 @@ class CreateAppController extends Controller {

ctx.request.validate<AppNewForm>('https://curveballjs.org/schemas/a12nserver/app-new-form.json');

ctx.privileges.require('admin');
const principalService = new PrincipalService(ctx.privileges);

const nickname = ctx.request.body.nickname;
const identity = ctx.request.body.url || uuidUrn();
Expand Down
5 changes: 3 additions & 2 deletions src/group/controller/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import { BadRequest, Conflict, NotFound } from '@curveball/http-errors';
import * as hal from '../formats/hal';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';

type NewPrincipalBody = {
nickname: string;
Expand All @@ -14,14 +14,15 @@ class GroupCollectionController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const groups = await principalService.findAll('group');
ctx.response.body = hal.collection(groups);

}

async post(ctx: Context) {

ctx.privileges.require('admin');
const principalService = new PrincipalService(ctx.privileges);

ctx.request.validate<NewPrincipalBody>(
'https://curveballjs.org/schemas/a12nserver/principal-new.json'
Expand Down
6 changes: 4 additions & 2 deletions src/group/controller/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import * as privilegeService from '../../privilege/service';
import * as hal from '../formats/hal';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';
import * as groupService from '../../group/service';
import { NotFound, Conflict } from '@curveball/http-errors';

Expand Down Expand Up @@ -31,6 +31,7 @@ class GroupController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const group = await principalService.findByExternalId(ctx.params.id, 'group');
const isAdmin = ctx.privileges.has('admin');
const members = await groupService.findMembers(group);
Expand All @@ -57,7 +58,7 @@ class GroupController extends Controller {

async put(ctx: Context) {

ctx.privileges.require('admin');
const principalService = new PrincipalService(ctx.privileges);
ctx.request.validate<EditPrincipalBody>(
'https://curveballjs.org/schemas/a12nserver/principal-edit.json'
);
Expand All @@ -77,6 +78,7 @@ class GroupController extends Controller {
*/
async patch(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
ctx.request.validate<GroupPatch>('https://curveballjs.org/schemas/a12nserver/group-patch.json');
const group = await principalService.findByExternalId(ctx.params.id, 'group');

Expand Down
88 changes: 0 additions & 88 deletions src/group/controller/member-collection.ts

This file was deleted.

3 changes: 2 additions & 1 deletion src/group/controller/new.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';
import { createGroupForm } from '../formats/html';
import { uuidUrn } from '../../crypto';

Expand All @@ -23,6 +23,7 @@ class CreateGroupController extends Controller {

async post(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
ctx.request.validate<GroupNewForm>('https://curveballjs.org/schemas/a12nserver/group-new-form.json');

ctx.privileges.require('admin');
Expand Down
2 changes: 1 addition & 1 deletion src/home/service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ServerStats } from '../types';
import { getPrincipalStats } from '../principal/service';
import { getPrincipalStats } from '../principal/privileged-service';
import { findPrivileges } from '../privilege/service';
import { lastTokenId } from '../oauth2/service';

Expand Down
3 changes: 2 additions & 1 deletion src/log/controller/user.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import { Forbidden } from '@curveball/http-errors';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';
import csv from '../formats/csv';
import * as logService from '../service';

class UserLogController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const user = await principalService.findByExternalId(ctx.params.id);
const log = await logService.findByUser(user);

Expand Down
5 changes: 3 additions & 2 deletions src/login/controller/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { EventType } from '../../log/types';
import { MFALoginSession } from '../../mfa/types';
import * as webAuthnService from '../../mfa/webauthn/service';
import { getSetting } from '../../server-settings';
import * as principalService from '../../principal/service';
import { hasUsers, PrincipalService } from '../../principal/privileged-service';
import * as userService from '../../user/service';
import { User } from '../../types';
import { isValidRedirect } from '../utilities';
Expand All @@ -17,7 +17,7 @@ class LoginController extends Controller {

async get(ctx: Context) {

const firstRun = !(await principalService.hasPrincipals());
const firstRun = !(await hasUsers());
if (firstRun) {
// The 'continue' query parameter contains the URL we want to redirect to after registration
const params = ctx.query.continue ? '?' + new URLSearchParams({continue: ctx.query.continue}) : '';
Expand All @@ -39,6 +39,7 @@ class LoginController extends Controller {

async post(ctx: Context<any>) {

const principalService = new PrincipalService('insecure');
let user: User;
try {
user = await principalService.findByIdentity('mailto:' + ctx.request.body.userName) as User;
Expand Down
4 changes: 3 additions & 1 deletion src/oauth2-client/controller/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Context } from '@curveball/core';
import { Forbidden, UnprocessableEntity } from '@curveball/http-errors';

import * as hal from '../formats/hal';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';
import { GrantType } from '../../types';
import { OAuth2Client } from '../types';
import { findByApp, create } from '../service';
Expand All @@ -14,6 +14,7 @@ class ClientCollectionController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const app = await principalService.findByExternalId(ctx.params.id, 'app');
if (ctx.auth.equals(app)) {
if (!ctx.privileges.has('admin')) {
Expand All @@ -28,6 +29,7 @@ class ClientCollectionController extends Controller {

async post(ctx: Context<any>) {

const principalService = new PrincipalService(ctx.privileges);
const app = await principalService.findByExternalId(ctx.params.id, 'app');
if (!ctx.privileges.has('admin')) {
throw new Forbidden('Only users with the "admin" privilege can inspect OAuth2 clients that are not your own');
Expand Down
4 changes: 3 additions & 1 deletion src/oauth2-client/controller/edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import * as hal from '../formats/hal';
import { Forbidden, NotFound, UnprocessableEntity } from '@curveball/http-errors';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';
import { findByClientId, edit } from '../service';
import * as oauth2Service from '../../oauth2/service';
import { GrantType } from '../../types';
Expand All @@ -11,6 +11,7 @@ class EditClientController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const app = await principalService.findByExternalId(ctx.params.id, 'app');
if (!ctx.privileges.has('admin')) {
throw new Forbidden('Only users with the "admin" privilege can add new OAuth2 clients');
Expand All @@ -27,6 +28,7 @@ class EditClientController extends Controller {

async post(ctx: Context<any>) {

const principalService = new PrincipalService(ctx.privileges);
const app = await principalService.findByExternalId(ctx.params.id, 'app');
if (!ctx.privileges.has('admin')) {
throw new Forbidden('Only users with the "admin" privilege can inspect OAuth2 clients that are not your own');
Expand Down
3 changes: 2 additions & 1 deletion src/oauth2-client/controller/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { Context } from '@curveball/core';
import * as hal from '../formats/hal';
import { Forbidden, NotFound } from '@curveball/http-errors';
import { findByClientId } from '../service';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';
import * as oauth2Service from '../../oauth2/service';

class ClientController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const user = await principalService.findByExternalId(ctx.params.id, 'app');
if (ctx.auth.equals(user)) {
if (!ctx.privileges.has('admin')) {
Expand Down
3 changes: 2 additions & 1 deletion src/oauth2-client/controller/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import Controller from '@curveball/controller';
import { Context } from '@curveball/core';
import * as siren from '../formats/siren';
import { Forbidden } from '@curveball/http-errors';
import * as principalService from '../../principal/service';
import { PrincipalService } from '../../principal/privileged-service';

class NewClientController extends Controller {

async get(ctx: Context) {

const principalService = new PrincipalService(ctx.privileges);
const user = await principalService.findByExternalId(ctx.params.id, 'app');
if (!ctx.privileges.has('admin')) {
throw new Forbidden('Only users with the "admin" privilege can add new OAuth2 clients');
Expand Down
Loading

0 comments on commit 89f47c0

Please sign in to comment.